Skip to content

feat(core): rename .auto-claude data folder to .aperant#1956

Open
AndyMik90 wants to merge 5 commits intodevelopfrom
fix/rename
Open

feat(core): rename .auto-claude data folder to .aperant#1956
AndyMik90 wants to merge 5 commits intodevelopfrom
fix/rename

Conversation

@AndyMik90
Copy link
Owner

@AndyMik90 AndyMik90 commented Mar 15, 2026

Base Branch

  • This PR targets the develop branch (required for all feature/fix PRs)
  • This PR targets main (hotfix only - maintainers)

Description

Renames all .auto-claude references to .aperant across the entire codebase (~122 files). Adds a migration dialog that detects existing .auto-claude/ folders and offers to rename them to .aperant/. Hard cut with no backwards-compatibility fallback logic.

Related Issue

N/A - Brand rename initiative

Type of Change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Test

Area

  • Frontend
  • Fullstack

AI Disclosure

  • This PR includes AI-generated code (Claude, Codex, Copilot, etc.)

Tool(s) used: Claude Code (Opus 4.6)
Testing level:

  • Untested

  • Lightly tested

  • Fully tested -- all tests pass, manually verified behavior

  • I understand what this PR does and how the underlying code works

Checklist

  • I have synced with develop branch
  • I have tested my changes locally
  • I have followed the code principles (SOLID, DRY, KISS)
  • My PR is small and focused (< 400 lines ideally)

Platform Testing Checklist

  • Windows tested (either on Windows or via CI)
  • macOS tested (either on macOS or via CI)
  • Linux tested (CI covers this)
  • Used centralized platform/ module instead of direct process.platform checks
  • No hardcoded paths (used findExecutable() or platform abstractions)

CI/Testing Requirements

  • All CI checks pass on all platforms (Windows, macOS, Linux)
  • All existing tests pass
  • New features include test coverage
  • Bug fixes include regression tests

Screenshots

N/A - No visual UI changes beyond the new migration dialog (text-only modal).

Feature Toggle

  • N/A - Feature is complete and ready for all users

Breaking Changes

Breaking: Yes

Details:

  • The .auto-claude/ data folder is now .aperant/. The migration dialog handles this automatically for existing projects.
  • MCP tool names changed from mcp__auto-claude__* to mcp__aperant__*.
  • Git worktree branch prefix changed from auto-claude/ to aperant/.
  • .gitignore retains both .auto-claude/ and .aperant/ entries so existing data folders remain ignored.

Changes Detail

Bulk Rename (~122 files)

  • All path constants, config values, and string references updated
  • Agent prompt files (coder.md, planner.md, qa_fixer.md, qa_reviewer.md) updated
  • Test files updated to use new naming
  • i18n keys updated in both en/ and fr/ locales

Migration Feature

  • needsMigration() and migrateProject() in project-initializer.ts
  • IPC handlers using IPC_CHANNELS constants and projectId-based lookup
  • Migration dialog in App.tsx gates project initialization
  • 9 unit tests for migration functions

Pre-PR Validation Fixes

  • Fixed MCP tool name mismatch (mcp__aperant__* alignment across registry and tool definitions)
  • Fixed IPC handler security (raw paths to projectId lookup via constants)
  • Replaced console.error with debugLog in migration code
  • Added ensureGitignoreEntries fallback in migrateProject()

All 4612 tests pass, TypeScript clean.

Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Automatic migration of legacy project data to the new Aperant layout
    • Migration prompt in the app to review or perform migration during project setup
  • Chores

    • Rebranded product and tooling from Auto Claude to Aperant across the UI and docs
    • Default project data/storage locations moved to the new Aperant paths
    • Updated integrations, tool identifiers, and localization to reflect Aperant branding

AndyMik90 and others added 2 commits March 15, 2026 13:33
Renames the project data directory from .auto-claude to .aperant across
the entire codebase (113 files) to align with the Aperant rebrand.

- All path constants, configs, worktree paths, branch prefixes updated
- MCP server ID changed from 'auto-claude' to 'aperant'
- Migration dialog added: detects .auto-claude folder and offers rename
- .gitignore includes both .auto-claude/ and .aperant/ for compatibility
- i18n strings updated (en + fr)
- All 207 test files pass (4603 tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-PR validation fixes for the .auto-claude → .aperant rename:
- Align MCP tool name constants (mcp__aperant__*) across registry and
  tool definitions to prevent silent agent tool call failures
- Use IPC_CHANNELS constants and projectId-based lookup instead of raw
  strings and paths in migration handlers (security)
- Add 9 unit tests for needsMigration() and migrateProject()
- Replace console.error with debugLog in migration code
- Add ensureGitignoreEntries fallback in migrateProject()
- Clear migrateError state on dialog close
@github-actions github-actions bot added area/frontend This is frontend only feature New feature or request size/XL Extra large (1000+ lines) labels Mar 15, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 15, 2026

📝 Walkthrough

Walkthrough

This PR rebrands the codebase from "Auto Claude" to "Aperant": renames directory literals (.auto-claude → .aperant), constants/types/fields (autoBuildPath → aperantPath, AutoBuildVersionInfo → AperantVersionInfo), updates MCP/tool identifiers, and adds migration APIs/handlers to detect and migrate existing .auto-claude project data to .aperant.

Changes

Cohort / File(s) Summary
Core Config & Paths
apps/desktop/src/shared/constants/config.ts, apps/desktop/src/main/config-paths.ts, apps/desktop/src/main/worktree-paths.ts, apps/desktop/src/shared/constants/ipc.ts
Renamed AUTO_BUILD_PATHS → APERANT_PATHS, changed default literals from .auto-claude/* to .aperant/*, updated APP_NAME, and added migration IPC channels.
Project Init & Migration
apps/desktop/src/main/project-initializer.ts, apps/desktop/src/main/__tests__/project-migration.test.ts, apps/desktop/src/main/project-store.ts
Added needsMigration() and migrateProject() (fs rename + .gitignore updates), renamed getAutoBuildPath → getAperantPath and related public methods/fields, updated store to use aperantPath.
IPC / Preload API
apps/desktop/src/shared/constants/ipc.ts, apps/desktop/src/preload/api/project-api.ts, apps/desktop/src/shared/types/ipc.ts
Exposed new IPC channels and preload methods: PROJECT_NEEDS_MIGRATION / PROJECT_MIGRATE and ProjectAPI.needsMigration / migrateProject; adjusted IPC types to AperantVersionInfo.
Renderer UI & Flows
apps/desktop/src/renderer/App.tsx, apps/desktop/src/renderer/components/Sidebar.tsx, apps/desktop/src/renderer/stores/project-store.ts
Added migration dialog + state, pre-check on project add, Sidebar callback onMigrationNeeded, wiring to new preload IPC; swapped autoBuildPath usages for aperantPath in UI flows.
AI / MCP Tooling
apps/desktop/src/main/ai/mcp/registry.ts, apps/desktop/src/main/ai/mcp/types.ts, apps/desktop/src/main/ai/tools/...
Renamed MCP server id and factory (auto-claude → aperant), updated tool metadata names/prefixes to mcp__aperant__*, and adjusted MCP mappings.
Env & Services (Insight/Changelog/Agents)
apps/desktop/src/main/insights/*, apps/desktop/src/main/changelog/*, apps/desktop/src/main/agent/*
Renamed parameters and methods to aperantSourcePath/aperantEnv, switched env loading and default dirs to .aperant, updated APERANT_PATHS usage across services.
IPC Handlers & Task Workflows
apps/desktop/src/main/ipc-handlers/**, apps/desktop/src/main/ai/runners/**, apps/desktop/src/main/ai/orchestration/**
Replaced AUTO_BUILD_PATHS and project.autoBuildPath with APERANT_PATHS and project.aperantPath across handlers, updated spec/worktree path lookups and branch naming (aperant/*).
Tests & Mocks
apps/desktop/src/**/__tests__/*, apps/desktop/src/renderer/lib/mocks/*
Updated many tests/mocks to reference .aperant and aperantPath; added migration test suite covering rename and .gitignore update scenarios.
Docs, i18n & Config
.gitignore, CLAUDE.md, .claude/commands/*, apps/desktop/src/shared/i18n/locales/*
Updated docs and translations from auto-claude → aperant, added .aperant entries to .gitignore, and added migration-related i18n strings.
Small runtime/UX tweaks
apps/desktop/src/main/terminal/*, apps/desktop/src/main/pty-daemon*, apps/desktop/src/main/sentry.ts
Socket/pipe names, temp dir prefixes, and sentry release strings updated from auto-claude → aperant; minor UX text updates.

Sequence Diagram(s)

sequenceDiagram
  participant Renderer as Renderer (UI)
  participant Preload as Preload API
  participant Main as Main Process (IPC)
  participant Initializer as Project Initializer
  participant FS as Filesystem

  Renderer->>Preload: needsMigration(projectId)
  Preload->>Main: IPC 'project:needs-migration'
  Main->>Initializer: needsMigration(projectPath)
  Initializer->>FS: exists('.auto-claude')? / exists('.aperant')?
  FS-->>Initializer: result
  Initializer-->>Main: boolean
  Main-->>Preload: IPC result
  Preload-->>Renderer: boolean

  alt needs migration
    Renderer->>Preload: migrateProject(projectId)
    Preload->>Main: IPC 'project:migrate'
    Main->>Initializer: migrateProject(projectPath)
    Initializer->>FS: rename('.auto-claude' -> '.aperant')
    Initializer->>FS: update/.gitignore (replace add .aperant)
    FS-->>Initializer: success/failure
    Initializer-->>Main: InitializationResult
    Main-->>Preload: IPC result
    Preload-->>Renderer: success/failure
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Hopping through code with a twitch of my nose,
From Claude to Aperant the fresh folder grows,
Paths renamed, tests updated, a migration song,
One hundred files dancing all day long —
May the rename be gentle and the migrations swift!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rename

@github-actions
Copy link
Contributor

github-actions bot commented Mar 15, 2026

Coverage Report for apps/desktop

Status Category Percentage Covered / Total
🔵 Lines 23.38% (🎯 22%) 12465 / 53300
🔵 Statements 23.05% (🎯 22%) 13014 / 56457
🔵 Functions 20.36% (🎯 19%) 2230 / 10949
🔵 Branches 18.1% (🎯 17%) 7112 / 39276
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
apps/desktop/src/main/config-paths.ts 0% 0% 0% 0% 22-138
apps/desktop/src/main/index.ts 0% 0% 0% 0% 7-710
apps/desktop/src/main/insights-service.ts 18.96% 0% 4.76% 19.29% 45, 48, 51, 54-245
apps/desktop/src/main/project-initializer.ts 39.47% 33.82% 50% 39.33% 13-151, 174, 201-213, 244-369, 432, 453-456
apps/desktop/src/main/project-store.ts 69.49% 57.22% 68.29% 70.19% 103-106, 137-143, 155, 174-212, 233-244, 249-250, 318, 335, 356-366, 394, 413-414, 418, 419, 438-446, 468, 542-550, 588, 626-662, 730, 745-766, 807, 819-820, 841, 853-854, 865-866, 879-883, 890-891, 900
apps/desktop/src/main/release-service.ts 0% 0% 0% 0% 33-804
apps/desktop/src/main/sentry.ts 16.36% 10% 15.38% 16.36% 62-91, 105-199, 221-225
apps/desktop/src/main/task-log-service.ts 2.73% 0% 0% 2.84% 9-13, 43-565
apps/desktop/src/main/task-state-manager.ts 85.53% 71.42% 90% 85.44% 120, 122, 169-181, 191-192, 242, 265-266, 308-316, 368, 370, 372, 379-380, 386-390
apps/desktop/src/main/terminal-name-generator.ts 15.78% 16.66% 33.33% 15.78% 13, 47-134
apps/desktop/src/main/title-generator.ts 12.5% 9.37% 33.33% 12.5% 14, 48-187
apps/desktop/src/main/worktree-paths.ts 25% 20% 33.33% 26.25% 26-27, 36-44, 65-66, 69-70, 81-82, 85, 93-94, 97, 106-196
apps/desktop/src/main/agent/agent-manager.ts 40.52% 30.96% 42.55% 41.12% 68-70, 86-128, 151-186, 203-266, 283, 299, 328-330, 333-334, 339-347, 364-366, 448-450, 453-454, 458, 570-572, 575-576, 580, 603, 664-676, 690-711, 777-877, 897-911, 946-999, 1018-1025, 1056-1064, 1086-1090, 1100-1107, 1137-1141, 1151-1157
apps/desktop/src/main/agent/agent-process.ts 34.12% 32.21% 35.13% 34.21% 45-94, 114-120, 201-211, 264-521, 598-600, 617-624, 651-726, 731-754, 758, 762, 767-768, 771-772, 782-804, 809-821, 858-860, 871, 880, 884, 891-892, 900-905, 915-917, 926-929, 961-967, 993-994, 1006-1008, 1013, 1019-1021, 1043-1046
apps/desktop/src/main/agent/agent-queue.ts 3.39% 0% 7.69% 3.43% 85-599
apps/desktop/src/main/ai/auth/codex-oauth.ts 4.97% 2.12% 0% 5.06% 30-42, 53-70, 117-564
apps/desktop/src/main/ai/config/agent-configs.ts 100% 90% 100% 100%
apps/desktop/src/main/ai/context/builder.ts 0% 0% 0% 0% 36-264
apps/desktop/src/main/ai/context/search.ts 0% 0% 0% 0% 15-119
apps/desktop/src/main/ai/context/types.ts 0% 0% 0% 0%
apps/desktop/src/main/ai/mcp/registry.ts 100% 100% 100% 100%
apps/desktop/src/main/ai/mcp/types.ts 0% 0% 0% 0%
apps/desktop/src/main/ai/memory/graph/incremental-indexer.ts 0% 0% 0% 0% 20-353
apps/desktop/src/main/ai/merge/file-evolution.ts 0.94% 0% 0% 1.04% 54-175, 192-538
apps/desktop/src/main/ai/merge/orchestrator.ts 0% 0% 0% 0% 102-720
apps/desktop/src/main/ai/merge/timeline-tracker.ts 0% 0% 0% 0% 85-640
apps/desktop/src/main/ai/orchestration/build-orchestrator.ts 0% 0% 0% 0% 44-786
apps/desktop/src/main/ai/project/analyzer.ts 0% 0% 0% 0% 43-552
apps/desktop/src/main/ai/project/project-indexer.ts 0.8% 0% 0% 0.84% 68-907
apps/desktop/src/main/ai/prompts/prompt-loader.ts 11.76% 5.04% 15.78% 12.66% 62-64, 95-97, 145-535
apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts 0% 0% 0% 0% 30-626
apps/desktop/src/main/ai/runners/commit-message.ts 91.52% 67.69% 100% 91.52% 138, 141, 144, 156, 159
apps/desktop/src/main/ai/runners/ideation.ts 100% 68.18% 100% 100%
apps/desktop/src/main/ai/runners/insights.ts 75.6% 48.57% 66.66% 76.92% 104-114, 121-130, 137-143, 207, 345-346
apps/desktop/src/main/ai/runners/roadmap.ts 64.05% 41.96% 46.15% 65.49% 171-176, 190-192, 226, 248-254, 303-308, 318, 334-341, 345-351, 369-372, 375-416
apps/desktop/src/main/ai/runners/github/pr-creator.ts 1.33% 0% 0% 1.36% 97-391
apps/desktop/src/main/ai/schema/structured-output.ts 43.52% 35.89% 57.14% 46.15% 47-62, 172, 203-214, 219, 303-364
apps/desktop/src/main/ai/security/security-profile.ts 68.42% 50% 50% 68.42% 80-81, 91-117, 136-141, 190, 206-209
apps/desktop/src/main/ai/security/validators/process-validators.ts 69.62% 64.91% 75% 69.62% 112-118, 123-125, 137-139, 142-144, 164, 189, 193, 245-260
apps/desktop/src/main/ai/tools/registry.ts 94.28% 85% 91.66% 95.23% 173-175, 204
apps/desktop/src/main/ai/tools/truncation.ts 13.04% 0% 0% 13.04% 57-112
apps/desktop/src/main/ai/tools/types.ts 100% 100% 100% 100%
apps/desktop/src/main/ai/tools/providers/fetch-browse.ts 12.5% 0% 0% 13.33% 16-44
apps/desktop/src/main/ai/worktree/worktree-manager.ts 0% 0% 0% 0% 30-301
apps/desktop/src/main/changelog/changelog-service.ts 17.71% 16.21% 29.03% 17.54% 62, 70-71, 85-91, 100, 112, 125-232, 267-507
apps/desktop/src/main/changelog/generator.ts 73.6% 49.15% 91.66% 73.6% 41, 76-89, 93-106, 111-112, 191-193, 214-215, 246-264, 279-280
apps/desktop/src/main/changelog/types.ts 0% 0% 0% 0%
apps/desktop/src/main/changelog/version-suggester.ts 0% 0% 0% 0% 23-250
apps/desktop/src/main/claude-code-settings/index.ts 100% 100% 100% 100%
apps/desktop/src/main/insights/config.ts 39.47% 19.23% 75% 40% 18-19, 29, 39, 52-80
apps/desktop/src/main/insights/paths.ts 27.27% 0% 0% 27.27% 16-55
apps/desktop/src/main/ipc-handlers/agent-events-handlers.ts 23.75% 14.09% 23.52% 24.02% 63, 68, 78-96, 121, 124-151, 167-173, 182-188, 195, 199, 203-236, 240, 244, 251-301, 308-380, 389-437, 445-460
apps/desktop/src/main/ipc-handlers/changelog-handlers.ts 11.5% 0.86% 4.54% 11.67% 36, 44-46, 51-53, 58-60, 65-67, 79-96, 106-119, 126-137, 144-233, 240-252, 260-266, 273-311, 319-353, 365-377, 385-397, 410-435, 447-478, 486-521
apps/desktop/src/main/ipc-handlers/claude-code-handlers.ts 9.48% 6.77% 6.52% 9.71% 44-211, 241, 257, 264, 274, 287-950, 971-972, 1026-1031, 1040-1068, 1077-1091, 1100-1128, 1137-1160, 1169-1214, 1225-1318, 1327-1431, 1442-1632
apps/desktop/src/main/ipc-handlers/env-handlers.ts 2.46% 0% 8.33% 2.73% 24, 48-294, 300-485, 492-524
apps/desktop/src/main/ipc-handlers/insights-handlers.ts 13.1% 0% 4% 13.1% 29-34, 48-54, 61-103, 111-117, 130-220, 229-235, 243-257, 265-274, 282-296, 304-313, 321-327, 335-341, 349-358, 366-375, 388-401, 411, 416, 421, 426, 431
apps/desktop/src/main/ipc-handlers/linear-handlers.ts 4.63% 0% 7.14% 4.76% 29-38, 50-80, 86-182, 190-222, 230-264, 272-372, 380-555
apps/desktop/src/main/ipc-handlers/mcp-handlers.ts 2.67% 0% 3.57% 2.84% 43-544, 557-565, 571-579
apps/desktop/src/main/ipc-handlers/memory-handlers.ts 8.6% 0% 3.84% 8.9% 95-178, 195-196, 207-290, 315-329, 338-348, 357-371, 391-408, 428-454, 484-545, 558-572, 581-591
apps/desktop/src/main/ipc-handlers/project-handlers.ts 18.13% 5.55% 13.15% 19.02% 35-235, 260-263, 283, 314-315, 325-326, 337-344, 356-363, 375-393, 403-420, 429-439, 452-457, 466-478, 491-501, 510-520, 529-539, 548-558, 567-577, 586-596
apps/desktop/src/main/ipc-handlers/roadmap-handlers.ts 6.09% 0% 2.38% 6.22% 33, 50-192, 201-203, 216-265, 278-320, 325-337, 347-403, 416-462, 470-622, 642-678, 689-734, 742-764, 780-906, 916, 920, 924
apps/desktop/src/main/ipc-handlers/settings-handlers.ts 32.17% 26.08% 16.32% 33.68% 33, 39, 42-52, 56-66, 70-80, 84-94, 98-108, 112-122, 126-137, 145-158, 169-185, 193, 226-234, 244-249, 258, 262-263, 297, 320-329, 333-342, 351, 353-363, 384-388, 396, 405, 421, 444-446, 475, 490, 495-502, 509-512, 526-541, 595-607, 619-671, 679-698, 722-735, 743-829, 845-889, 898-912, 919-924, 933-971, 980-998, 1007-1032, 1041-1060, 1069-1076, 1085-1094, 1104, 1112-1132
apps/desktop/src/main/ipc-handlers/context/project-context-handlers.ts 6.25% 0% 16.66% 6.25% 24-78, 96-125, 134-150
apps/desktop/src/main/ipc-handlers/context/utils.ts 3.27% 0% 0% 3.33% 20-106, 118-227
apps/desktop/src/main/ipc-handlers/github/autofix-handlers.ts 20.07% 8.02% 17.46% 20% 109-418, 435-439, 448-454, 462-468, 476-482, 490-496, 504-528, 537-669, 678-684, 695-696, 725, 743, 747, 753, 770, 771, 778-796, 830-880, 934-963
apps/desktop/src/main/ipc-handlers/github/pr-handlers.ts 25.54% 14.49% 18.93% 25.89% 97-152, 191-226, 265, 403-454, 462-495, 605-613, 633, 637, 670-677, 695-745, 795-796, 800-803, 805-808, 813-817, 908-912, 918-922, 931-938, 952-956, 962-966, 980-1009, 1046, 1048, 1049, 1051, 1103-1110, 1215, 1240-1241, 1348-1436, 1520-1521, 1528-1530, 1551-1555, 1565-1571, 1586-1591, 1614-1629, 1673, 1714-1729, 1774, 1779-1789, 1806-1854, 1868, 1875-1884, 1892-1901, 1909-1968, 1978-1996, 2006-2007, 2020-2031, 2059-2060, 2070-2071, 2093-2100, 2140-2143, 2157-2158, 2179-2188, 2207, 2213-2228, 2242-2444, 2452-2488, 2496-2539, 2547-2601, 2614-2646, 2654-2676, 2684-2723, 2732-2895, 2903-3037, 3045-3096, 3104-3377, 3395-3466, 3474-3499, 3507-3560, 3568-3630, 3649-3680, 3691-3706, 3715-3716
apps/desktop/src/main/ipc-handlers/github/spec-utils.ts 0% 0% 0% 0% 25-249
apps/desktop/src/main/ipc-handlers/github/triage-handlers.ts 39.85% 24.39% 37.03% 40.44% 102-195, 295, 315-342, 387-393, 419-423, 432-438, 446-452, 463-464, 503-513, 522-577
apps/desktop/src/main/ipc-handlers/github/utils.ts 6% 0% 0% 6.38% 80-354
apps/desktop/src/main/ipc-handlers/gitlab/autofix-handlers.ts 5.97% 0% 4.54% 6.25% 33-413, 428-430, 439-444, 452-456, 464-468, 476-480, 488-501, 510-514, 522-594, 603-634
apps/desktop/src/main/ipc-handlers/gitlab/mr-review-handlers.ts 4.97% 1.09% 2.56% 5.15% 54-350, 366-387, 397-398, 407-490, 499-588, 596-619, 627-679, 687-710, 718-740, 748-765, 774-847, 855-970
apps/desktop/src/main/ipc-handlers/gitlab/spec-utils.ts 29.23% 23.46% 33.33% 30.68% 56-103, 119, 122, 128, 142, 149, 154, 156, 159-171, 197-205, 248-255, 266-490
apps/desktop/src/main/ipc-handlers/gitlab/triage-handlers.ts 6.66% 0% 6.89% 6.97% 41-274, 289-291, 300-305, 313-317, 325-443, 452-456
apps/desktop/src/main/ipc-handlers/gitlab/utils.ts 2.29% 0% 0% 2.53% 23-66, 74-116, 132-231, 247-409
apps/desktop/src/main/ipc-handlers/ideation/idea-manager.ts 0% 0% 0% 0% 21-271
apps/desktop/src/main/ipc-handlers/ideation/session-manager.ts 0% 0% 0% 0% 20-65
apps/desktop/src/main/ipc-handlers/ideation/task-converter.ts 0% 0% 0% 0% 28-282
apps/desktop/src/main/ipc-handlers/task/crud-handlers.ts 16.27% 11.58% 22.22% 16.49% 25, 28-30, 34-117, 139-141, 170-171, 182-183, 188-191, 194, 218-271, 304-308, 352-443, 457-642, 663-733, 745-770
apps/desktop/src/main/ipc-handlers/task/execution-handlers.ts 1.4% 0% 4.34% 1.41% 34-111, 127-359, 368-389, 405-576, 594-886, 897-898, 910-964, 979-1397
apps/desktop/src/main/ipc-handlers/task/logs-handlers.ts 97.95% 82.14% 100% 97.95% 123
apps/desktop/src/main/ipc-handlers/task/plan-file-utils.ts 10.63% 6.38% 14.28% 10.77% 39-65, 83, 90-229, 256-257, 261-272, 294-637
apps/desktop/src/main/ipc-handlers/task/worktree-handlers.ts 3.45% 1.35% 3.07% 3.55% 101-133, 150-274, 955-968, 982-1747, 1763-1867, 1879-1961, 1972-2381, 2393-2511, 2527-2588, 2603-2666, 2678-2821, 2832-2840, 2851-2867, 2878-2894, 2906-2970, 2982-3107
apps/desktop/src/main/ipc-handlers/terminal/worktree-handlers.ts 2% 0% 3.33% 2.07% 53-245, 294-482, 496-1225, 1233, 1240-1247, 1260, 1267-1274
apps/desktop/src/main/services/profile/profile-manager.ts 42.52% 58.69% 53.33% 43.02% 26-27, 38, 56, 62, 68, 74, 79, 113, 140, 155-158, 184-291
apps/desktop/src/main/terminal/cli-integration-handler.ts 42.35% 36.99% 41.02% 42.51% 45-83, 123-171, 183, 228-244, 476-817, 841, 1018-1048, 1286-1294, 1362, 1407-1472, 1519-1678
apps/desktop/src/main/terminal/pty-daemon-client.ts 0% 0% 0% 0% 17-466
apps/desktop/src/main/terminal/pty-daemon.ts 0% 0% 0% 0% 16-528
apps/desktop/src/main/updater/path-resolver.ts 48.38% 25% 50% 48.38% 16, 32, 51, 62-72, 81-84, 95-100
apps/desktop/src/main/utils/git-isolation.ts 31.81% 28.57% 50% 31.81% 153-214
apps/desktop/src/main/utils/profile-manager.ts 86.2% 62.5% 100% 86.2% 23-24, 65-66
apps/desktop/src/main/utils/spec-number-lock.ts 0% 0% 0% 0% 23-223
apps/desktop/src/main/utils/spec-path-helpers.ts 92.59% 88% 100% 100% 20, 63
apps/desktop/src/main/utils/worktree-cleanup.ts 0% 0% 0% 0% 66-277
apps/desktop/src/preload/api/project-api.ts 19.14% 100% 18.18% 18.18% 158-167, 178-217, 228-295
apps/desktop/src/renderer/App.tsx 0% 0% 0% 0% 76-1287
apps/desktop/src/renderer/components/AddProjectModal.tsx 0% 0% 0% 0% 28-299
apps/desktop/src/renderer/components/AgentTools.tsx 0% 0% 0% 0% 80-1384
apps/desktop/src/renderer/components/GitHubSetupModal.tsx 0% 0% 0% 0% 68-927
apps/desktop/src/renderer/components/Sidebar.tsx 0% 0% 0% 0% 81-514
apps/desktop/src/renderer/components/WelcomeScreen.tsx 0% 0% 0% 0% 22-92
apps/desktop/src/renderer/components/context/MemoriesTab.tsx 0% 0% 0% 0% 43-409
apps/desktop/src/renderer/components/github-prs/components/PRDetail.tsx 55.63% 54.33% 51.31% 57.02% 72, 229, 261-262, 269-270, 296-298, 318-328, 375-378, 393, 418-461, 508, 513-522, 571, 590-591, 601-602, 618-627, 633-647, 653-679, 732-738, 765-815, 833-839, 855-861, 886-909, 915-929, 939-958, 968, 1017-1054, 1060-1064, 1089-1504
apps/desktop/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx 0% 0% 0% 0% 59-145
apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx 0% 0% 0% 0% 45-968
apps/desktop/src/renderer/components/onboarding/OllamaModelSelector.tsx 0.82% 0% 0% 0.88% 112-517
apps/desktop/src/renderer/components/onboarding/OnboardingWizard.tsx 69.23% 41.66% 76.92% 66.66% 101-104, 113-116, 122-125, 148-177, 183-187
apps/desktop/src/renderer/components/project-settings/GeneralSettings.tsx 0% 0% 0% 0% 46-213
apps/desktop/src/renderer/components/project-settings/GitHubIntegrationSection.tsx 0% 0% 0% 0% 35-214
apps/desktop/src/renderer/components/project-settings/IntegrationSettings.tsx 0% 0% 0% 0% 79-500
apps/desktop/src/renderer/components/project-settings/LinearIntegrationSection.tsx 0% 0% 0% 0% 32-163
apps/desktop/src/renderer/components/project-settings/MemoryBackendSection.tsx 0% 0% 0% 0% 30-147
apps/desktop/src/renderer/components/project-settings/SecuritySettings.tsx 0% 0% 0% 0% 50-443
apps/desktop/src/renderer/components/project-settings/index.ts 0% 0% 0% 0%
apps/desktop/src/renderer/components/project-settings/hooks/useProjectSettings.ts 0% 0% 0% 0% 79-384
apps/desktop/src/renderer/components/settings/AdvancedSettings.tsx 0% 0% 0% 0% 36-585
apps/desktop/src/renderer/components/settings/GeneralSettings.tsx 0% 0% 0% 0% 30-268
apps/desktop/src/renderer/components/settings/common/InitializationGuard.tsx 0% 0% 0% 0% 20-28
apps/desktop/src/renderer/components/settings/integrations/GitHubIntegration.tsx 0% 0% 0% 0% 16-684
apps/desktop/src/renderer/components/settings/integrations/LinearIntegration.tsx 0% 0% 0% 0% 32-236
apps/desktop/src/renderer/components/settings/sections/SectionRouter.tsx 0% 0% 0% 0% 75-198
apps/desktop/src/renderer/components/shared/MemoryConfigPanel.tsx 0% 0% 0% 0% 59-288
apps/desktop/src/renderer/lib/terminal-theme.ts 100% 100% 100% 100%
apps/desktop/src/renderer/lib/mocks/infrastructure-mock.ts 2.85% 100% 0% 2.85% 8-158
apps/desktop/src/renderer/lib/mocks/mock-data.ts 100% 100% 100% 100%
apps/desktop/src/renderer/lib/mocks/project-mock.ts 4.16% 0% 0% 4.16% 9-132
apps/desktop/src/renderer/stores/project-store.ts 35.59% 17.89% 50% 34.14% 55, 76-78, 92-94, 179-180, 219-455
apps/desktop/src/renderer/stores/settings-store.ts 1.05% 0% 2.12% 0.57% 87-554
apps/desktop/src/shared/constants.ts 0% 0% 0% 0%
apps/desktop/src/shared/types.ts 0% 0% 0% 0%
apps/desktop/src/shared/constants/config.ts 100% 100% 100% 100%
apps/desktop/src/shared/constants/ipc.ts 100% 100% 100% 100%
apps/desktop/src/shared/types/ipc.ts 0% 0% 0% 0%
apps/desktop/src/shared/types/project.ts 0% 0% 0% 0%
apps/desktop/src/shared/types/settings.ts 0% 0% 0% 0%
apps/desktop/src/shared/types/task.ts 0% 0% 0% 0%
apps/desktop/src/shared/types/terminal.ts 0% 0% 0% 0%
Generated in workflow #7812 for commit cba0502 by the Vitest Coverage Report Action

Comment on lines +458 to +462
ipcMain.handle(IPC_CHANNELS.PROJECT_MIGRATE, async (_, projectId: string) => {
const project = projectStore.getProject(projectId);
if (!project) return { success: false, error: 'Project not found' };
return migrateProject(project.path);
});

This comment was marked as outdated.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request implements a significant branding change by renaming the core data folder from .auto-claude to .aperant. The change impacts various parts of the application, including file paths, configuration, and internal references. A key aspect of this update is the introduction of a migration mechanism to smoothly transition existing projects to the new naming convention, ensuring data integrity and user experience during the changeover.

Highlights

  • Core Renaming: All references to the .auto-claude data folder have been systematically renamed to .aperant across approximately 122 files in the codebase. This is a hard cut with no backwards-compatibility fallback logic for the folder name itself.
  • Migration Dialog Implementation: A new migration dialog has been added to detect existing .auto-claude folders in projects and offer to rename them to .aperant. This includes updating .gitignore entries and reporting success or failure.
  • Tooling and Git Updates: MCP tool names have been updated from mcp__auto-claude__* to mcp__aperant__*. Additionally, the Git worktree branch prefix has changed from auto-claude/ to aperant/.
  • Gitignore Compatibility: The .gitignore file now includes entries for both .auto-claude/ and .aperant/ to ensure compatibility during the transition period.
  • New Unit Tests: Nine new unit tests were added specifically for the migration functions to ensure the renaming and .gitignore updates work as expected.
Changelog
  • .claude/commands/setup-statusline.md
    • Updated references to the status file name from .auto-claude-status to .aperant-status.
  • .gitignore
    • Updated the comment from 'Auto Claude Generated' to 'Aperant Generated'.
    • Added .aperant/, .aperant-security.json, and .aperant-status entries.
    • Retained .auto-claude/, .auto-claude-security.json, and .auto-claude-status entries for compatibility.
  • CLAUDE.md
    • Updated paths for resetting PR review state from .auto-claude/github/ to .aperant/github/.
    • Updated spec directory structure references from .auto-claude/specs/ to .aperant/specs/.
    • Updated project data path in example from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/prompts/coder.md
    • Updated spec location path from ./auto-claude/specs/ to ./.aperant/specs/.
    • Updated worktree path examples from .../.auto-claude/worktrees/ to .../.aperant/worktrees/.
    • Updated git add command exclusion from :!.auto-claude to :!.aperant.
    • Updated git commit message prefix from auto-claude: to aperant:.
    • Updated build progress file path from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/prompts/planner.md
    • Updated spec file location from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/prompts/qa_fixer.md
    • Updated spec file location from .auto-claude/specs/ to .aperant/specs/.
    • Updated worktree path example from /path/to/.auto-claude/worktrees/ to /path/to/.aperant/worktrees/.
    • Updated git add command exclusion from :!.auto-claude to :!.aperant.
  • apps/desktop/prompts/qa_reviewer.md
    • Updated spec file location from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/tests/e2e/smoke.test.ts
    • Updated directory creation for test projects from .auto-claude to .aperant.
  • apps/desktop/src/tests/integration/rate-limit-subtask-recovery.test.ts
    • Updated test spec directory path from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/tests/integration/task-lifecycle.test.ts
    • Updated test spec directory path from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/tests/file-watcher.test.ts
    • Updated spec directory paths in various test cases from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/tests/ipc-handlers.test.ts
    • Updated directory creation for test projects from auto-claude/specs to aperant/specs.
    • Updated spec directory paths in test cases from .auto-claude/specs to .aperant/specs.
  • apps/desktop/src/main/tests/project-migration.test.ts
    • Added a new test file to validate the needsMigration and migrateProject functions.
    • Implemented mocks for fs functions to simulate file system operations during migration tests.
  • apps/desktop/src/main/tests/project-store.test.ts
    • Updated directory detection for projects from .auto-claude to .aperant.
    • Updated spec directory paths in various test cases from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/agent/agent-manager.ts
    • Updated spec directory resolution path from .auto-claude to .aperant.
  • apps/desktop/src/main/agent/agent-process.ts
    • Updated comments and references to the project's .env file from .auto-claude/.env to .aperant/.env.
  • apps/desktop/src/main/agent/agent-queue.ts
    • Updated output directories for ideation and roadmap files from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/client/tests/factory.test.ts
    • Updated spec directory path in test setup from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/ai/config/tests/agent-configs.test.ts
    • Updated MCP server names in test descriptions and assertions from auto-claude to aperant.
  • apps/desktop/src/main/ai/config/agent-configs.ts
    • Renamed MCP tool constants (e.g., TOOL_UPDATE_SUBTASK_STATUS) from mcp__auto-claude__* to mcp__aperant__*.
    • Updated mcpServers arrays for various agent configurations from auto-claude to aperant.
  • apps/desktop/src/main/ai/context/builder.ts
    • Updated project index file path from .auto-claude/project_index.json to .aperant/project_index.json.
  • apps/desktop/src/main/ai/context/search.ts
    • Updated SKIP_DIRS constant to exclude .aperant instead of auto-claude and .auto-claude.
  • apps/desktop/src/main/ai/context/types.ts
    • Updated comment for ProjectIndex interface from .auto-claude/project_index.json to .aperant/project_index.json.
  • apps/desktop/src/main/ai/mcp/tests/client.test.ts
    • Updated MCP server names in test cases from auto-claude to aperant.
  • apps/desktop/src/main/ai/mcp/tests/registry.test.ts
    • Updated MCP server names and test descriptions from auto-claude to aperant.
  • apps/desktop/src/main/ai/mcp/registry.ts
    • Updated id for the custom build management server from auto-claude to aperant.
    • Updated comments and interface options to refer to aperant instead of auto-claude.
  • apps/desktop/src/main/ai/mcp/types.ts
    • Updated McpServerId type definition from auto-claude to aperant.
  • apps/desktop/src/main/ai/memory/graph/incremental-indexer.ts
    • Updated ignored directories in IncrementalIndexer from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/merge/file-evolution.ts
    • Updated comments and storage directory path from .auto-claude/baselines/ to .aperant/baselines/.
  • apps/desktop/src/main/ai/merge/orchestrator.ts
    • Updated worktree locations and storage directory path from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/merge/timeline-tracker.ts
    • Updated worktree file content path and storage path from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/orchestration/tests/qa-loop.test.ts
    • Updated spec directory path in test setup from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/ai/orchestration/tests/qa-reports.test.ts
    • Updated spec directory path in test setup from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/ai/orchestration/tests/recovery-manager.test.ts
    • Updated spec directory path in test setup from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/ai/orchestration/build-orchestrator.ts
    • Updated comment for specDir interface from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/ai/project/analyzer.ts
    • Updated security profile filename from .auto-claude-security.json to .aperant-security.json.
    • Updated custom allowlist filename from .auto-claude-allowlist to .aperant-allowlist.
  • apps/desktop/src/main/ai/project/project-indexer.ts
    • Updated SKIP_DIRS constant to exclude .aperant instead of .auto-claude.
  • apps/desktop/src/main/ai/prompts/prompt-loader.ts
    • Updated comment and path for project_index.json from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts
    • Updated worktree path patterns from .auto-claude to .aperant.
    • Updated fallback relative spec path from ./auto-claude/specs/ to ./aperant/specs/.
  • apps/desktop/src/main/ai/runners/tests/commit-message.test.ts
    • Updated spec directory path in test cases from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/ai/runners/tests/ideation.test.ts
    • Updated output directory in test configurations from .auto-claude/ideation to .aperant/ideation.
  • apps/desktop/src/main/ai/runners/tests/roadmap.test.ts
    • Updated output directory in test configurations from .auto-claude/roadmap to .aperant/roadmap.
  • apps/desktop/src/main/ai/runners/commit-message.ts
    • Updated spec directory path from .auto-claude/specs to .aperant/specs and removed fallback to auto-claude.
  • apps/desktop/src/main/ai/runners/github/pr-creator.ts
    • Updated spec file path from .auto-claude/specs to .aperant/specs.
  • apps/desktop/src/main/ai/runners/ideation.ts
    • Updated spec directory path in toolContext from .auto-claude/specs to .aperant/specs.
  • apps/desktop/src/main/ai/runners/insights.ts
    • Updated paths for project_index.json, roadmap, and tasks from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/runners/roadmap.ts
    • Updated output directory and spec directory path in RoadmapConfig and toolContext from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/security/security-profile.ts
    • Updated comments and filenames for security profiles and allowlists from .auto-claude to .aperant.
  • apps/desktop/src/main/ai/security/validators/process-validators.ts
    • Updated BLOCKED_PROCESS_NAMES to include aperant instead of auto-claude.
  • apps/desktop/src/main/ai/session/tests/progress-tracker.test.ts
    • Updated file path in test cases from /project/.auto-claude/specs/ to /project/.aperant/specs/.
  • apps/desktop/src/main/ai/tools/tests/registry.test.ts
    • Updated MCP server names in test cases from auto-claude to aperant.
  • apps/desktop/src/main/ai/tools/auto-claude/get-build-progress.ts
    • Updated tool name and comment from mcp__auto-claude__get_build_progress to mcp__aperant__get_build_progress.
  • apps/desktop/src/main/ai/tools/auto-claude/get-session-context.ts
    • Updated tool name and comment from mcp__auto-claude__get_session_context to mcp__aperant__get_session_context.
  • apps/desktop/src/main/ai/tools/auto-claude/index.ts
    • Updated comment to reflect the new tool naming convention mcp__aperant__*.
  • apps/desktop/src/main/ai/tools/auto-claude/record-discovery.ts
    • Updated tool name and comment from mcp__auto-claude__record_discovery to mcp__aperant__record_discovery.
  • apps/desktop/src/main/ai/tools/auto-claude/record-gotcha.ts
    • Updated tool name and comment from mcp__auto-claude__record_gotcha to mcp__aperant__record_gotcha.
  • apps/desktop/src/main/ai/tools/auto-claude/update-qa-status.ts
    • Updated tool name and comment from mcp__auto-claude__update_qa_status to mcp__aperant__update_qa_status.
  • apps/desktop/src/main/ai/tools/auto-claude/update-subtask-status.ts
    • Updated tool name and comment from mcp__auto-claude__update_subtask_status to mcp__aperant__update_subtask_status.
  • apps/desktop/src/main/ai/tools/registry.ts
    • Updated tool constants from mcp__auto-claude__* to mcp__aperant__*.
    • Updated logic for removing MCP servers to protect aperant instead of auto-claude.
  • apps/desktop/src/main/ai/tools/truncation.ts
    • Updated comment and spillover directory path from .auto-claude/tool-output/ to .aperant/tool-output/.
  • apps/desktop/src/main/ai/tools/types.ts
    • Updated comment for specDir interface from .auto-claude/specs/ to .aperant/specs/.
  • apps/desktop/src/main/ai/worktree/worktree-manager.ts
    • Updated comments, worktree paths, and branch names from auto-claude to aperant.
  • apps/desktop/src/main/changelog/tests/changelog-service.integration.test.ts
    • Updated specs directory path in test setup from .auto-claude/specs to .aperant/specs.
  • apps/desktop/src/main/changelog/changelog-service.ts
    • Updated comments for debug logging to refer to aperant/.env instead of auto-claude/.env.
  • apps/desktop/src/main/config-paths.ts
    • Renamed APP_NAME constant from auto-claude to aperant.
    • Updated memories directory path from ~/.auto-claude/memories to ~/.aperant/memories.
  • apps/desktop/src/main/insights/paths.ts
    • Updated INSIGHTS_DIR constant from .auto-claude/insights to .aperant/insights.
  • apps/desktop/src/main/ipc-handlers/README.md
    • Updated initialization command from PROJECT_INITIALIZE - Initialize .auto-claude directory to PROJECT_INITIALIZE - Initialize .aperant directory.
  • apps/desktop/src/main/ipc-handlers/context/utils.ts
    • Updated memory database path from ~/.auto-claude/memories to ~/.aperant/memories.
  • apps/desktop/src/main/ipc-handlers/env-handlers.ts
    • Updated memory database path placeholder from ~/.auto-claude/memories to ~/.aperant/memories.
  • apps/desktop/src/main/ipc-handlers/github/tests/runner-env-handlers.test.ts
    • Updated autoBuildPath in test project creation from .auto-claude to .aperant.
  • apps/desktop/src/main/ipc-handlers/github/autofix-handlers.ts
    • Updated comment and path for auto-fix configuration from .auto-claude/github/config.json to .aperant/github/config.json.
  • apps/desktop/src/main/ipc-handlers/github/pr-handlers.ts
    • Updated GitHub directory path and PR logs path from .auto-claude/github to .aperant/github.
  • apps/desktop/src/main/ipc-handlers/github/triage-handlers.ts
    • Updated GitHub directory path from .auto-claude/github to .aperant/github.
  • apps/desktop/src/main/ipc-handlers/gitlab/autofix-handlers.ts
    • Updated GitLab directory path from .auto-claude/gitlab to .aperant/gitlab.
  • apps/desktop/src/main/ipc-handlers/gitlab/mr-review-handlers.ts
    • Updated GitLab directory path from .auto-claude/gitlab to .aperant/gitlab.
  • apps/desktop/src/main/ipc-handlers/gitlab/triage-handlers.ts
    • Updated GitLab directory path from .auto-claude/gitlab to .aperant/gitlab.
  • apps/desktop/src/main/ipc-handlers/project-handlers.ts
    • Imported needsMigration and migrateProject functions.
    • Updated console warnings for missing project folders from .auto-claude to .aperant.
    • Updated autoBuildPath to .aperant upon successful project initialization.
    • Updated comments regarding version tracking for .aperant.
    • Added new IPC handlers for PROJECT_NEEDS_MIGRATION and PROJECT_MIGRATE.
  • apps/desktop/src/main/ipc-handlers/sections/task-section.txt
    • Updated autoBuildDir and specDir paths from .auto-claude to .aperant.
  • apps/desktop/src/main/ipc-handlers/sections/task_extracted.txt
    • Updated autoBuildDir and specDir paths from .auto-claude to .aperant.
  • apps/desktop/src/main/ipc-handlers/task/tests/logs-integration.test.ts
    • Updated autoBuildPath and spec directory paths in test cases from .auto-claude to .aperant.
  • apps/desktop/src/main/ipc-handlers/task/tests/worktree-branch-validation.test.ts
    • Updated branch names and test descriptions from auto-claude to aperant.
  • apps/desktop/src/main/ipc-handlers/task/crud-handlers.ts
    • Updated autoBuildDir and specsDir paths from .auto-claude to .aperant.
  • apps/desktop/src/main/ipc-handlers/task/execution-handlers.ts
    • Updated git clean command to exclude .aperant instead of .auto-claude.
  • apps/desktop/src/main/ipc-handlers/task/worktree-handlers.ts
    • Updated comments regarding aperant/ branch prefix.
    • Updated branch name patterns from auto-claude/ to aperant/.
    • Updated spec directory paths and storage directory paths from .auto-claude to .aperant.
  • apps/desktop/src/main/ipc-handlers/terminal/worktree-handlers.ts
    • Updated .env path, project index path, and excluded worktree prefixes from .auto-claude to .aperant.
  • apps/desktop/src/main/project-initializer.ts
    • Imported renameSync from fs.
    • Updated GITIGNORE_ENTRIES from .auto-claude/ to .aperant/.
    • Updated comments and variable names to reflect .aperant instead of .auto-claude.
    • Added needsMigration function to check for old directory existence.
    • Added migrateProject function to rename the directory and update .gitignore.
  • apps/desktop/src/main/project-store.ts
    • Updated console warnings for missing project folders from .auto-claude to .aperant.
    • Updated logic for determining autoBuildPath to use getAutoBuildPath which now returns .aperant.
  • apps/desktop/src/main/release-service.ts
    • Updated worktrees directory path from .auto-claude/worktrees/tasks to .aperant/worktrees/tasks.
  • apps/desktop/src/main/services/profile/profile-manager.test.ts
    • Updated profile file path in tests from auto-claude to aperant.
  • apps/desktop/src/main/services/profile/profile-manager.ts
    • Updated profile file path from auto-claude to aperant.
  • apps/desktop/src/main/task-log-service.ts
    • Updated comments for specsRelPath parameter from auto-claude/specs to aperant/specs.
  • apps/desktop/src/main/utils/git-isolation.ts
    • Updated expected branch name from auto-claude/ to aperant/.
  • apps/desktop/src/main/utils/profile-manager.test.ts
    • Updated profile file path in tests from auto-claude to aperant.
  • apps/desktop/src/main/utils/profile-manager.ts
    • Updated profile file path from auto-claude to aperant.
  • apps/desktop/src/main/utils/spec-number-lock.ts
    • Updated lock directory and specs base directory from .auto-claude to .aperant.
  • apps/desktop/src/main/utils/spec-path-helpers.ts
    • Updated comment for specsBaseDir parameter from .auto-claude/specs to .aperant/specs.
  • apps/desktop/src/main/utils/worktree-cleanup.ts
    • Updated branch naming convention and worktree path comments from auto-claude to aperant.
  • apps/desktop/src/main/worktree-paths.ts
    • Updated worktree directory constants from .auto-claude to .aperant.
  • apps/desktop/src/preload/api/project-api.ts
    • Added needsMigration and migrateProject to the ProjectAPI interface and its implementation.
  • apps/desktop/src/renderer/App.tsx
    • Added new state variables for showMigrateDialog, migrationProject, isMigrating, and migrateError.
    • Updated project initialization logic to include a check for migration before showing the init dialog.
    • Implemented handleMigrate and handleSkipMigrate functions for the migration dialog.
    • Added the Migrate Project Data Dialog component to the UI.
  • apps/desktop/src/renderer/tests/project-store-tabs.test.ts
    • Updated autoBuildPath in test project creation from .auto-claude to .aperant.
  • apps/desktop/src/renderer/components/AgentTools.tsx
    • Updated MCP server names and tool names in agent configurations and MCP server definitions from auto-claude to aperant.
  • apps/desktop/src/renderer/components/tests/ProjectTabBar.test.tsx
    • Updated autoBuildPath in test project creation from .auto-claude to .aperant.
  • apps/desktop/src/renderer/components/tests/SortableProjectTab.test.tsx
    • Updated autoBuildPath in test project creation from .auto-claude to .aperant.
  • apps/desktop/src/renderer/components/context/MemoriesTab.tsx
    • Updated memory path placeholder from ~/.auto-claude/memories to ~/.aperant/memories.
  • apps/desktop/src/renderer/components/github-prs/components/PRDetail.tsx
    • Updated PR logs path comment from .auto-claude/github/pr/logs_ to .aperant/github/pr/logs_.
  • apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx
    • Updated memory path comment from ~/.auto-claude/graphs/ to ~/.aperant/graphs/.
  • apps/desktop/src/renderer/components/project-settings/MemoryBackendSection.tsx
    • Updated memory path comments and placeholders from ~/.auto-claude/memories/ to ~/.aperant/memories/.
  • apps/desktop/src/renderer/components/project-settings/SecuritySettings.tsx
    • Updated memory path comments and placeholders from ~/.auto-claude/memories/ to ~/.aperant/memories/.
  • apps/desktop/src/renderer/components/task-detail/task-review/CreatePRDialog.test.tsx
    • Updated branch names in test cases from auto-claude/ to aperant/.
  • apps/desktop/src/renderer/lib/mocks/infrastructure-mock.ts
    • Updated database path in mock data from ~/.auto-claude/graphs to ~/.aperant/graphs.
  • apps/desktop/src/renderer/lib/mocks/project-mock.ts
    • Added mocks for needsMigration and migrateProject functions.
  • apps/desktop/src/renderer/stores/project-store.ts
    • Updated console logs and autoBuildPath update logic to reflect the new .aperant folder name.
  • apps/desktop/src/shared/constants/config.ts
    • Updated AUTO_BUILD_PATHS constants and getSpecsDir function to use .aperant instead of .auto-claude.
  • apps/desktop/src/shared/constants/ipc.ts
    • Added new IPC channels: PROJECT_NEEDS_MIGRATION and PROJECT_MIGRATE.
  • apps/desktop/src/shared/i18n/locales/en/dialogs.json
    • Updated initialization dialog strings to refer to .aperant.
    • Added new strings for the project migration dialog, including title, description, action, success, and error messages.
  • apps/desktop/src/shared/i18n/locales/en/settings.json
    • Updated autoClaudePath description and placeholder to refer to aperant.
  • apps/desktop/src/shared/i18n/locales/fr/dialogs.json
    • Updated French initialization dialog strings to refer to .aperant.
    • Added new French strings for the project migration dialog.
  • apps/desktop/src/shared/i18n/locales/fr/settings.json
    • Updated French autoClaudePath description and placeholder to refer to aperant.
  • apps/desktop/src/shared/types/ipc.ts
    • Added needsMigration and migrateProject to the ElectronAPI interface.
  • apps/desktop/src/shared/types/project.ts
    • Updated dbPath comment in MemoryProviderConfig from ~/.auto-claude/memories to ~/.aperant/memories.
    • Updated comment for AgentMcpOverride to refer to .aperant/.env.
    • Updated comment for AutoBuildVersionInfo to refer to .aperant.
  • apps/desktop/src/shared/types/terminal.ts
    • Updated worktreePath comment in TerminalWorktreeConfig from .auto-claude/worktrees/terminal/ to .aperant/worktrees/terminal/.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request executes a comprehensive rename from .auto-claude to .aperant across the codebase, including the addition of a migration dialog for existing projects. The changes are extensive and largely correct. I've identified a couple of minor issues regarding the .gitignore migration logic and the search exclusion list that could be improved for consistency.

Comment on lines 15 to 20
const SKIP_DIRS = new Set([
'node_modules', '.git', '__pycache__', '.venv', 'venv', 'dist', 'build',
'.next', '.nuxt', 'target', 'vendor', '.idea', '.vscode', 'auto-claude',
'.auto-claude', '.pytest_cache', '.mypy_cache', 'coverage', '.turbo', '.cache',
'.next', '.nuxt', 'target', 'vendor', '.idea', '.vscode',
'.aperant', '.pytest_cache', '.mypy_cache', 'coverage', '.turbo', '.cache',
'out',
]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To maintain consistency with the .gitignore changes (which keep both .auto-claude/ and .aperant/), it would be beneficial to also keep .auto-claude in this SKIP_DIRS set. This will prevent the search functionality from indexing old data directories in projects that have been migrated.

Suggested change
const SKIP_DIRS = new Set([
'node_modules', '.git', '__pycache__', '.venv', 'venv', 'dist', 'build',
'.next', '.nuxt', 'target', 'vendor', '.idea', '.vscode', 'auto-claude',
'.auto-claude', '.pytest_cache', '.mypy_cache', 'coverage', '.turbo', '.cache',
'.next', '.nuxt', 'target', 'vendor', '.idea', '.vscode',
'.aperant', '.pytest_cache', '.mypy_cache', 'coverage', '.turbo', '.cache',
'out',
]);
const SKIP_DIRS = new Set([
'node_modules', '.git', '__pycache__', '.venv', 'venv', 'dist', 'build',
'.next', '.nuxt', 'target', 'vendor', '.idea', '.vscode',
'.auto-claude', '.aperant', '.pytest_cache', '.mypy_cache', 'coverage', '.turbo', '.cache',
'out',
]);

Comment on lines +423 to +435
// Update .gitignore: replace .auto-claude/ with .aperant/
const gitignorePath = path.join(projectPath, '.gitignore');
try {
let content = readFileSync(gitignorePath, 'utf-8');
content = content.replace(/\.auto-claude\//g, '.aperant/');
content = content.replace(/\.auto-claude-security\.json/g, '.aperant-security.json');
content = content.replace(/\.auto-claude-status/g, '.aperant-status');
writeFileSync(gitignorePath, content, 'utf-8');
} catch {
// .gitignore update is non-critical
}
// Ensure .aperant/ is ignored even if .auto-claude/ was never in .gitignore
ensureGitignoreEntries(projectPath, ['.aperant/']);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current logic replaces .auto-claude entries in .gitignore, which contradicts the goal of keeping both for backward compatibility. A safer approach would be to add the new .aperant entries without removing the old ones. The ensureGitignoreEntries function could be useful here.

    // Update .gitignore to ensure new paths are ignored, preserving old ones.
    ensureGitignoreEntries(projectPath, [
      '.aperant/',
      '.aperant-security.json',
      '.aperant-status',
    ]);

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 34

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (11)
apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts (1)

332-335: ⚠️ Potential issue | 🟡 Minor

Missed rename: commit message prefix still uses auto-claude:.

The commit message template still references auto-claude: while the PR objective is to rename all references to aperant. This should be updated to maintain consistency with the rebranding.
,

🔧 Proposed fix
    `5. **Commit your changes:**\n` +
    `   \`\`\`bash\n` +
    `   git add .\n` +
-   `   git commit -m "auto-claude: ${subtask.id} - ${subtask.description.slice(0, 50)}"\n` +
+   `   git commit -m "aperant: ${subtask.id} - ${subtask.description.slice(0, 50)}"\n` +
    `   \`\`\`\n` +
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts` around lines
332 - 335, The commit message template still uses the old prefix "auto-claude:";
update the string in the git commit line (the template that builds `git commit
-m "auto-claude: ${subtask.id} - ${subtask.description.slice(0, 50)}"`) to use
the new brand prefix "aperant:" so the commit message becomes `aperant:
${subtask.id} - ${subtask.description.slice(0, 50)}`.
apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx (1)

118-118: ⚠️ Potential issue | 🟠 Major

Incomplete branding update: auto_claude_memory defaults should be renamed to align with .aperant directory structure.

The file uses .aperant for the storage path (line 910) but retains auto_claude_memory for the database default (lines 118, 249) and placeholder (line 905). Update these to use a consistent branding name (e.g., aperant_memory or aperant). This pattern also appears in SecuritySettings.tsx:429, MemoryBackendSection.tsx:133, and other files—apply the same rename consistently across the codebase.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx` at line
118, Replace the outdated branding value "auto_claude_memory" with the new
consistent name (e.g., "aperant_memory") wherever it is used as a default or
placeholder in GraphitiStep.tsx (the database default entry and the placeholder
near the storage path usage), and make the same replacement in the other
referenced components (SecuritySettings.tsx, MemoryBackendSection.tsx) so
defaults, placeholders, and any related keys match the .aperant directory
branding; update any variable names/comments that reference auto_claude_memory
to the new identifier to keep the codebase consistent.
apps/desktop/src/main/ai/runners/__tests__/ideation.test.ts (1)

284-295: ⚠️ Potential issue | 🟡 Minor

Test name and assertions are out of sync (missing outputDir assertion).

The test claims to validate both projectDir and outputDir, but it only asserts project path content. Add an assertion for the .aperant/ideation output path to prevent regressions.

💡 Suggested test fix
   const streamArgs = mockStreamText.mock.calls[0][0];
   const systemPrompt = streamArgs.system as string;
   expect(systemPrompt).toContain('/my/project');
+  expect(systemPrompt).toContain('/my/project/.aperant/ideation');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ai/runners/__tests__/ideation.test.ts` around lines 284
- 295, The test for runIdeation names both projectDir and outputDir but only
asserts the projectDir; update the test (using mockStreamText and inspecting
streamArgs.system as systemPrompt) to also assert that the outputDir is included
by adding an expectation that systemPrompt contains the output path
'/my/project/.aperant/ideation' (e.g.,
expect(systemPrompt).toContain('/my/project/.aperant/ideation')); leave the
existing projectDir assertion intact.
apps/desktop/src/renderer/components/AgentTools.tsx (1)

1186-1192: ⚠️ Potential issue | 🟡 Minor

Always-enabled row still uses legacy autoClaude translation keys.

If translations were renamed to aperant, this will surface stale text (or raw keys). Update this row to settings:mcp.servers.aperant.* for naming consistency with the rest of the migration.

Minimal key update
-<span className="text-sm font-medium">{t('settings:mcp.servers.autoClaude.name')}</span>
-<p className="text-xs text-muted-foreground">{t('settings:mcp.servers.autoClaude.description')} ({t('settings:mcp.alwaysEnabled')})</p>
+<span className="text-sm font-medium">{t('settings:mcp.servers.aperant.name')}</span>
+<p className="text-xs text-muted-foreground">{t('settings:mcp.servers.aperant.description')} ({t('settings:mcp.alwaysEnabled')})</p>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/AgentTools.tsx` around lines 1186 -
1192, Update the stale translation keys in the AgentTools component: replace
t('settings:mcp.servers.autoClaude.name') and
t('settings:mcp.servers.autoClaude.description') with
t('settings:mcp.servers.aperant.name') and
t('settings:mcp.servers.aperant.description') respectively (the surrounding
layout including the always-enabled note t('settings:mcp.alwaysEnabled') stays
unchanged); these strings appear in the Auto-Claude/aperant row in
AgentTools.tsx where the span and paragraph render the name and description.
apps/desktop/src/main/ipc-handlers/sections/task-section.txt (1)

778-784: 🧹 Nitpick | 🔵 Trivial

Consider using getSpecsDir() helper for consistency.

Similar to the pattern at line 261, this code uses an inline fallback instead of the getSpecsDir() helper function used elsewhere in the file. Consolidating to use the helper would reduce code duplication and improve maintainability.

♻️ Proposed refactor to use helper function
-      const autoBuildDir = project.autoBuildPath || '.aperant';
-      const specDir = path.join(
-        project.path,
-        autoBuildDir,
-        'specs',
-        task.specId
-      );
+      const specsBaseDir = getSpecsDir(project.autoBuildPath);
+      const specDir = path.join(project.path, specsBaseDir, task.specId);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/sections/task-section.txt` around lines
778 - 784, Replace the inline autoBuildDir and specDir path assembly with the
existing getSpecsDir helper to match the pattern used at line 261: remove the
autoBuildDir and path.join usage that builds specDir from
project.autoBuildPath/project.path and task.specId, and instead call
getSpecsDir(...) (the same signature used elsewhere, e.g., getSpecsDir(project,
task.specId) or getSpecsDir(project) plus specId) to obtain the specs directory;
assign specDir from that helper and keep task.specId usage consistent.
apps/desktop/src/main/utils/worktree-cleanup.ts (1)

132-142: 🧹 Nitpick | 🔵 Trivial

Pre-existing: process.platform usage violates coding guidelines.

Line 134 uses process.platform !== 'win32' directly. Per coding guidelines, platform detection should use functions from apps/desktop/src/main/platform/ such as isWindows().

This is pre-existing code, but consider addressing it while touching this file.

♻️ Suggested refactor
+import { isWindows } from '../platform';
...
   // All retries exhausted - try shell rm -rf as fallback on Unix
   // Node's rm() can fail with ENOTEMPTY on macOS .app bundles
-  if (process.platform !== 'win32') {
+  if (!isWindows()) {
     try {

As per coding guidelines: "Never use process.platform directly. Import platform detection from apps/desktop/src/main/platform/ instead."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/utils/worktree-cleanup.ts` around lines 132 - 142,
Replace the direct process.platform check with the centralized platform helper:
import and call isWindows() from the platform utilities and change the condition
to if (!isWindows()) around the block that logs and calls
execFileSync('/bin/rm', ['-rf', dirPath], ...); ensure you add the import for
isWindows at the top of the module and keep existing references to logPrefix and
dirPath unchanged so behavior remains the same.
apps/desktop/src/renderer/components/project-settings/SecuritySettings.tsx (1)

426-442: ⚠️ Potential issue | 🟠 Major

Replace hardcoded UI literals with react-i18next translation keys.

Lines 426, 438, and 441 contain hardcoded user-facing text in TSX. These must use react-i18next keys with entries in both en/settings.json and fr/settings.json translation files.

Suggested direction
+ import { useTranslation } from 'react-i18next';

 export function SecuritySettings(...) {
+  const { t } = useTranslation(['settings']);
   ...
-  <p className="text-xs text-muted-foreground">
-    Stored in ~/.aperant/memories/
-  </p>
+  <p className="text-xs text-muted-foreground">
+    {t('settings:security.memory.storedIn', { path: '~/.aperant/memories/' })}
+  </p>

-  <p className="text-xs text-muted-foreground">
-    Custom storage location. Default: ~/.aperant/memories/
-  </p>
+  <p className="text-xs text-muted-foreground">
+    {t('settings:security.memory.customLocationDefault', { path: '~/.aperant/memories/' })}
+  </p>

-  <Input placeholder="~/.aperant/memories" ... />
+  <Input placeholder={t('settings:security.memory.pathPlaceholder')} ... />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/project-settings/SecuritySettings.tsx`
around lines 426 - 442, In SecuritySettings.tsx, replace the hardcoded
user-facing literals (the paragraph "Stored in ~/.aperant/memories/", the Label
"Database Path (Optional)", the paragraph "Custom storage location. Default:
~/.aperant/memories/", and the two Input placeholders "auto_claude_memory" and
"~/.aperant/memories") with react-i18next keys using useTranslation (e.g.,
t('settings.memoryStored'), t('settings.dbPathLabel'), t('settings.dbPathHelp'),
t('settings.placeholderMemory'), t('settings.placeholderDbPath')) and keep
wiring to envConfig.memoryDatabase and envConfig.memoryDbPath unchanged; then
add corresponding entries to en/settings.json and fr/settings.json with
appropriate translations. Ensure you import and call useTranslation at the top
of SecuritySettings and replace the literal strings with the t(...) calls.
apps/desktop/src/main/utils/git-isolation.ts (1)

166-169: 🧹 Nitpick | 🔵 Trivial

Minor: Comment still references "auto-claude branch"

The security comment on lines 166-169 mentions "another task's auto-claude branch" but the actual branch pattern is now aperant/. Consider updating for consistency.

📝 Suggested comment update
     // SECURITY: Use strict exact-match validation (not prefix matching) to prevent
-    // accidentally deleting a different task's auto-claude branch. When git rev-parse
+    // accidentally deleting a different task's aperant branch. When git rev-parse
     // returns an unexpected branch, we MUST fall back to the expected pattern rather
     // than risking deletion of the wrong branch. This is critical for data safety.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/utils/git-isolation.ts` around lines 166 - 169, Update
the security comment in git-isolation.ts so it references the current branch
naming scheme (`aperant/`) instead of "auto-claude branch"; specifically edit
the exact comment block that starts with "SECURITY: Use strict exact-match
validation..." to mention preventing deletion of another task's `aperant/`
branch and ensure the wording makes clear we must fall back to the expected
`aperant/` pattern when git rev-parse returns an unexpected branch.
apps/desktop/src/renderer/components/project-settings/MemoryBackendSection.tsx (1)

128-145: 🧹 Nitpick | 🔵 Trivial

Hardcoded strings violate i18n guidelines (pre-existing issue)

The user-facing text in this component uses hardcoded English strings rather than react-i18next translation keys. While the path updates from .auto-claude to .aperant are correct, these strings should use i18n for proper localization:

  • Line 128: "Database Name"
  • Line 130: "Name for the memory database (stored in ~/.aperant/memories/)"
  • Line 140: "Database Path (Optional)"
  • Line 142: "Custom storage location. Default: ~/.aperant/memories/"

This appears to be a pre-existing issue not introduced by this PR. Consider addressing in a follow-up.

As per coding guidelines: "All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/components/project-settings/MemoryBackendSection.tsx`
around lines 128 - 145, Replace the hardcoded English strings in
MemoryBackendSection.tsx with react-i18next translation keys: import and call
useTranslation (e.g., const { t } = useTranslation()) at the top of the
component and replace "Database Name", "Name for the memory database (stored in
~/.aperant/memories/)", "Database Path (Optional)", and "Custom storage
location. Default: ~/.aperant/memories/" with t('memory.databaseName'),
t('memory.databaseDescription'), t('memory.databasePathOptional'), and
t('memory.databasePathDescription') (and also translate placeholders like
"auto_claude_memory" and "~/.aperant/memories"); ensure the new keys are added
to the locale resources in the i18n files in a follow-up change.
apps/desktop/src/renderer/lib/mocks/project-mock.ts (1)

9-16: ⚠️ Potential issue | 🟡 Minor

Update mock autoBuildPath to .aperant for consistency.

autoBuildPath still points to .../auto-claude (Line 15), which conflicts with this PR’s canonical folder rename and can skew renderer/mock behavior.

Suggested fix
-      autoBuildPath: `${projectPath}/auto-claude`,
+      autoBuildPath: `${projectPath}/.aperant`,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/lib/mocks/project-mock.ts` around lines 9 - 16, The
mock addProject function returns an object whose autoBuildPath is hardcoded to
`${projectPath}/auto-claude`; update this to use the new canonical folder name
`.aperant` by changing the autoBuildPath generation in addProject to
`${projectPath}/.aperant` (keep other fields like id, name, path and settings
using DEFAULT_PROJECT_SETTINGS unchanged) so mock behavior matches the PR
rename.
apps/desktop/src/main/ai/config/agent-configs.ts (1)

477-486: ⚠️ Potential issue | 🟠 Major

Keep the legacy auto-claude alias in MCP_SERVER_NAME_MAP.

mapMcpServerName() resolves user-provided MCP override strings. Dropping the old name here turns the rename into a silent breaking change for any existing config that still says auto-claude.

🛠️ Proposed fix
 const MCP_SERVER_NAME_MAP: Record<string, string> = {
   context7: 'context7',
   'graphiti-memory': 'memory',
   graphiti: 'memory',
   memory: 'memory',
   linear: 'linear',
   electron: 'electron',
   puppeteer: 'puppeteer',
+  'auto-claude': 'aperant',
   'aperant': 'aperant',
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ai/config/agent-configs.ts` around lines 477 - 486, The
MCP_SERVER_NAME_MAP is missing the legacy "auto-claude" alias which
mapMcpServerName() still needs to resolve older configs; add an entry for
"auto-claude" mapping to the current server key (e.g. map "auto-claude" ->
"context7") inside MCP_SERVER_NAME_MAP so older user-provided MCP override
strings continue to work and are not silently broken.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.claude/commands/setup-statusline.md:
- Around line 124-126: The guide currently mixes two path names —
`.aperant-status` and `auto-claude/statusline.py` — causing ambiguity; pick one
canonical path (e.g., `.aperant-status/statusline.py` or
`auto-claude/statusline.py`) and update all occurrences in the document so they
match consistently (references in the checklist, the "Try running the command"
example, and the later steps around lines 139–150). Search for strings
`.aperant-status` and `auto-claude/statusline.py` and replace them with the
chosen canonical path in the setup-statusline.md content, and ensure the example
command (the `python ... --format compact` line) and any path-verification steps
reference that same canonical path.

In `@apps/desktop/src/main/__tests__/ipc-handlers.test.ts`:
- Around line 144-147: The fixture directory created in setupTestProject() is
missing the leading dot so tests create "aperant/specs" instead of
".aperant/specs"; update setupTestProject() to create the hidden directory (use
path.join(TEST_PROJECT_PATH, ".aperant", "specs") with mkdirSync and {
recursive: true }) so the TEST_PROJECT_PATH fixture matches the handlers'
expected ".aperant" directory and preserves initialized-project detection.

In `@apps/desktop/src/main/__tests__/project-migration.test.ts`:
- Around line 65-68: The test uses hardcoded POSIX strings for PROJECT,
OLD_PATH, NEW_PATH, and GITIGNORE which won't match path.join outputs on
Windows; update those constants in project-migration.test.ts to be constructed
with path.join(...) (e.g., use path.join('test','project') for PROJECT and then
path.join(PROJECT, '.auto-claude') / path.join(PROJECT, '.aperant') /
path.join(PROJECT, '.gitignore')) so the mocked fs helpers match the paths
produced by project-initializer.ts across platforms.

In `@apps/desktop/src/main/agent/agent-manager.ts`:
- Line 378: The code currently computes resolvedSpecDir using a hardcoded path
('.aperant/specs'), which can diverge from other phases that use
getSpecsDir(project?.autoBuildPath); change resolvedSpecDir to use
getSpecsDir(project?.autoBuildPath) when specDir is undefined and then append
the taskId (i.e., resolvedSpecDir = specDir ??
path.join(getSpecsDir(project?.autoBuildPath), taskId)); update references to
resolvedSpecDir accordingly so spec creation and execution use the same
directory resolution logic.

In `@apps/desktop/src/main/agent/agent-queue.ts`:
- Line 228: The hardcoded '.aperant' fragment is duplicated; replace occurrences
(the outputDir declaration using outputDir = path.join(projectPath, '.aperant',
'ideation') and the other use at line 472) with the centralized constant or
helper used elsewhere (e.g., APERANT_DIR, APERANT_ROOT, or
getAperantPath/projectAperantDir) so both locations derive the same base path;
update the imports to pull that constant/helper and join its returned value with
'ideation' where needed to avoid path drift.

In `@apps/desktop/src/main/ai/memory/graph/incremental-indexer.ts`:
- Line 49: The ignore list in incremental-indexer.ts currently only excludes the
internal folder pattern '**/.aperant/**', so add the legacy internal folder
pattern '**/.auto-claude/**' alongside '**/.aperant/**' wherever it appears (the
occurrences around the existing '**/.aperant/**' entries, including the second
occurrence near line 316) so both internal folders are excluded from indexing
during migration; update the ignore array or glob ignore construction that
contains the '**/.aperant/**' string to include '**/.auto-claude/**'.

In `@apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts`:
- Around line 107-109: The fallback that builds the spec path in
subtask-prompt-generator.ts is using "./aperant/specs/..." which omits the dot
and mismatches the canonical data folder (.aperant) used in
WORKTREE_PATH_PATTERNS; update the returned path construction (the code that
uses resolvedSpec, parts, and returns `./aperant/specs/${parts[parts.length -
1]}`) to include the leading dot so it returns "./.aperant/specs/<name>"
(keeping the same parts extraction logic) to ensure path consistency.

In `@apps/desktop/src/main/ai/security/security-profile.ts`:
- Line 5: Update the top docstring in
apps/desktop/src/main/ai/security/security-profile.ts to accurately describe
where profiles are read from: replace “.aperant/ config” with the actual
root-level filenames used by the module (projectDir/.aperant-security.json and
projectDir/.aperant-allowlist) so the module comment matches the implemented
storage semantics in this file.

In `@apps/desktop/src/main/ai/tools/registry.ts`:
- Line 224: Extract the hardcoded 'aperant' string into a single constant (e.g.,
PROTECTED_SERVER_ID or PROTECTED_TOOL_ID) at the top of
apps/desktop/src/main/ai/tools/registry.ts and replace the literal in the
conditional "if (mapped && mapped !== 'aperant')" with that constant; update any
other occurrences in the same file that refer to the same protected server id so
renames are centralized and avoid drift (search for uses of the literal
'aperant' in this module and replace them with the new constant).

In `@apps/desktop/src/main/changelog/changelog-service.ts`:
- Line 57: Comments in changelog-service.ts incorrectly state the code reads
DEBUG from ".aperant/.env" while the actual implementation uses the path
returned by getAutoBuildSourcePath(); update the comment lines that mention
".aperant/.env" (the ones near the DEBUG checks) to accurately say they load
.env from getAutoBuildSourcePath() (or explicitly from the auto-build
source/prompts path), or alternatively modify the logic to load the .env from an
actual ".aperant" directory if that behavior is intended; locate references to
getAutoBuildSourcePath() and the DEBUG checks and make the comment change or
code change accordingly so the comment matches the behavior.

In `@apps/desktop/src/main/config-paths.ts`:
- Around line 73-77: The comment and variable name in getMemoriesDir are
misleading: rename the variable and update the comment so it accurately reflects
the path being constructed (e.g., change legacyPath to aperantMemoriesPath or
currentMemoriesPath and update the comment to say this is the current
.aperant/memories location rather than “legacy”), or if you intended to keep a
true legacy path, change the path value to the actual legacy location; ensure
all references in getMemoriesDir (the variable name and the explanatory comment)
match the chosen intent.

In `@apps/desktop/src/main/ipc-handlers/github/pr-handlers.ts`:
- Around line 2736-2737: Replace the duplicated path construction with the
centralized helper: use getGitHubDir(project) instead of manually building
githubDir via path.join(project.path, ".aperant", "github"); then build
reviewPath by joining the result of getGitHubDir(project) with "pr" and
`review_${prNumber}.json`; update references to githubDir and reviewPath in this
scope (the variables around the current usage of githubDir, reviewPath,
prNumber) so the code relies on getGitHubDir(project) to avoid path drift.
- Around line 2511-2514: The code writes to tmpFile (const tmpFile =
join(project.path, ".aperant", "tmp_comment_body.txt") and then writeFileSync)
without ensuring the ".aperant" directory exists and uses a fixed filename that
can collide; update the handler to ensure the directory is created (e.g.,
fs.mkdirSync(join(project.path, ".aperant"), { recursive: true }) or equivalent)
before writing and replace the fixed filename with a unique temp filename (use
fs.mkdtempSync, include process.pid/timestamp or use the system tmp API) to
avoid concurrent collisions, then write the body to that unique path and ensure
any needed cleanup after posting the comment; reference tmpFile, join, and
writeFileSync in your changes.

In `@apps/desktop/src/main/ipc-handlers/gitlab/mr-review-handlers.ts`:
- Line 777: Replace the inline path construction that sets gitlabDir (const
gitlabDir = path.join(project.path, '.aperant', 'gitlab')) with a call to the
centralized helper getGitLabDir(project); locate the assignment to gitlabDir in
mr-review-handlers and use getGitLabDir(project) instead so all code uses the
single source of truth for the GitLab directory.

In `@apps/desktop/src/main/ipc-handlers/gitlab/triage-handlers.ts`:
- Line 98: getGitLabDir currently returns path.join(project.path, '.aperant',
'gitlab') without the project-bound validation used in
gitlab/autofix-handlers.ts; update getGitLabDir to build the resolved gitlabDir
(path.join(project.path, '.aperant', 'gitlab')) and then perform the same
explicit boundary check used in autofix-handlers.ts (e.g., resolve both the
project root/expected project base and gitlabDir and ensure gitlabDir is a
subpath of the expected project directory); if the check fails, throw or return
an error instead of returning the path. Ensure you reference and mirror the
validation logic from gitlab/autofix-handlers.ts and keep the check inside the
getGitLabDir function.

In `@apps/desktop/src/main/ipc-handlers/project-handlers.ts`:
- Around line 458-462: The PROJECT_MIGRATE IPC handler currently calls
migrateProject(project.path) but does not persist the updated autoBuildPath into
projectStore, leaving the in-memory project uninitialized; modify the handler
(IPC_CHANNELS.PROJECT_MIGRATE) to await the migrateProject call, extract the new
autoBuildPath (or new path) from its result, assign it to project.autoBuildPath,
and persist the change back into projectStore using the existing persistence
method (e.g., projectStore.updateProject(projectId, { autoBuildPath: newPath })
or projectStore.saveProject(project)). Keep returning the migrateProject result
after persisting so the renderer sees the updated, initialized project.

In `@apps/desktop/src/main/ipc-handlers/README.md`:
- Line 21: Update the README entry for the IPC handler
`project:has-local-source` to replace the stale phrase "auto-claude source" with
"aperant source" so the naming matches the rest of the PR; locate the line that
currently reads "`project:has-local-source` - Check if project has local
auto-claude source" and change the description to mention "aperant" instead.

In `@apps/desktop/src/main/ipc-handlers/sections/task_extracted.txt`:
- Around line 261-262: Replace the duplicated fallback logic that computes
autoBuildDir and specDir with the shared helper: call
getSpecsDir(project.autoBuildPath) to obtain the auto-build dir and then build
specDir via path.join(project.path, specsDir, 'specs', task.specId). Concretely,
remove the autoBuildDir = project.autoBuildPath || '.aperant' code and instead
use const specsDir = getSpecsDir(project.autoBuildPath); const specDir =
path.join(project.path, specsDir, 'specs', task.specId); apply the same
replacement at the other mentioned sites (the other occurrences around lines
778–783 and 1210) so all handlers consistently use getSpecsDir.

In `@apps/desktop/src/main/ipc-handlers/sections/task-section.txt`:
- Line 1210: Replace the inline specDir construction with the existing helper by
calling getSpecsDir(project, task.specId) instead of using
path.join(project.path, project.autoBuildPath || '.aperant', 'specs',
task.specId); find the occurrence that sets specDir and swap it to use
getSpecsDir(...) so behavior and fallback logic are consistent with other
handlers that use getSpecsDir.
- Around line 261-262: Replace the inline fallback and join with the existing
helper: call getSpecsDir(project.autoBuildPath) to get the specs base directory,
then compute specDir by joining that value with task.specId (e.g. const specsDir
= getSpecsDir(project.autoBuildPath); const specDir = path.join(specsDir,
task.specId)); update the references in this handler (currently using
autoBuildDir/project.autoBuildPath and specDir) to use specsDir so path
construction is consistent with other handlers.

In `@apps/desktop/src/main/ipc-handlers/task/crud-handlers.ts`:
- Around line 465-466: The spec path is being built manually using autoBuildDir
and a hardcoded 'specs' folder; replace this with the centralized helper by
calling getSpecsDir(project.autoBuildPath) and then join the returned path with
task.specId to form specDir. Update the code around where specDir is defined
(the block that currently uses autoBuildDir/project.path/'specs'/task.specId) to
use getSpecsDir(project.autoBuildPath) so it matches the approach used in
TASK_CREATE and TASK_DELETE and preserves future changes to the specs
subdirectory structure.

In `@apps/desktop/src/main/ipc-handlers/task/execution-handlers.ts`:
- Line 479: Replace the production console.log call that prints "[TASK_REVIEW]
Cleaned untracked files in main (excluding .aperant)" with the app's production
logger/warning API (e.g., processLogger.warn or the structured logger used
elsewhere) so the message is visible in packaged Electron builds; find the
console.log(...) in execution-handlers.ts (the call containing that exact
message) and change it to use the structured logger method, preserving the
message text and any contextual metadata (task id, path, etc.) as additional
fields.
- Around line 471-473: Replace the hardcoded '.aperant' exclude in the git clean
call with the computed specsBaseDir: in the spawnSync invocation that currently
calls spawnSync(getToolPath('git'), ['clean', '-fd', '-e', '.aperant'], { cwd:
project.path, ... }), pass the exclusion derived from specsBaseDir instead (and
ensure it is expressed relative to project.path if needed, e.g., via
path.relative(project.path, specsBaseDir) or using path.basename if specsBaseDir
is inside the project) so the exclusion follows the resolved
project.autoBuildPath; keep the same spawnSync/getToolPath('git') call and cwd:
project.path settings.

In `@apps/desktop/src/main/ipc-handlers/task/worktree-handlers.ts`:
- Around line 3037-3038: The default PR title uses the old product prefix
("auto-claude:") while branchName is namespaced as `aperant/...`; update the
prTitle assignment to use the new prefix so PR metadata matches the branch
namespace—replace `auto-claude:` with `aperant:` in the prTitle expression
(`const prTitle = options?.title || \`auto-claude: ${task.specId}\``) so it
becomes `const prTitle = options?.title || \`aperant: ${task.specId}\`` (keeping
task.specId and optional override logic unchanged).
- Around line 2702-2703: The orphan-detection uses a hardcoded mainSpecsDir
which builds ".aperant/specs" and can be wrong for projects with a custom
autoBuildPath; update the logic that sets mainSpecsDir (the variable used
alongside tasks and taskLookupSuccessful) to derive the specs directory from
project.autoBuildPath (falling back to the default ".aperant" if autoBuildPath
is unset) before joining the "specs" segment so orphan detection uses the
project's configured build path.

In `@apps/desktop/src/main/project-initializer.ts`:
- Around line 301-316: Before creating the .aperant directory, add a check for
the legacy folder '.auto-claude' (using existsSync with path.join(projectPath,
'.auto-claude')) and if it exists return an error (similar shape to the existing
return when .aperant exists) preventing initialization; update the logic
surrounding dotAutoBuildPath, existsSync, and mkdirSync in the initialization
flow so the presence of '.auto-claude' blocks creating '.aperant' and surfaces a
clear error message instructing the user to migrate or remove the legacy folder.

In `@apps/desktop/src/main/services/profile/profile-manager.ts`:
- Around line 17-21: Comments in profile-manager.ts still reference the old name
"auto-claude" and should be updated to "aperant"; locate occurrences (e.g., near
the getProfilesFilePath function and any other comment blocks mentioning
"auto-claude") and replace those comment strings with "aperant" so all comments
consistently reflect the new path/name.

In `@apps/desktop/src/main/utils/profile-manager.ts`:
- Around line 14-18: The doc comments in profile-manager.ts still refer to the
old "auto-claude" name while the implementation uses "aperant"; update those
stale references—search for occurrences in the file (e.g., the file header
comment and the comment above getProfilesFilePath / any other mentions around
the profiles.json path) and replace "auto-claude" with "aperant" (or otherwise
make the comment consistent with getProfilesFilePath and the path join using
'aperant') so the comments match the code.

In `@apps/desktop/src/renderer/App.tsx`:
- Around line 420-431: The init flow must be gated while needsMigration() is in
flight to prevent concurrent migrate/init dialogs: add a per-project "migration
check pending" flag (e.g., a Map or Set keyed by project.id) and set it before
calling window.electronAPI.needsMigration(...) and clear it in both success and
catch branches (the current code where you call setMigrationProject,
setMigrateError, setShowMigrateDialog should remain). Update the initialization
effect (the effect that opens the init dialog for a project) to check this
pending guard and skip/return if migration check is pending for that project.id
so the migrate path runs exclusively; apply the same guard in the other
add-project path referenced (lines ~660-674).

In `@apps/desktop/src/renderer/components/AgentTools.tsx`:
- Around line 289-292: The new 'aperant' entry in AgentTools (object key
'aperant' with properties name and description in AgentTools.tsx) uses hardcoded
English strings; replace those literals with react-i18next translation keys
(e.g. t('servers.aperant.name') and t('servers.aperant.description') inside the
component where ListChecks is already used), then add corresponding entries for
servers.aperant.name and servers.aperant.description to both the en/*.json and
fr/*.json translation files; ensure the code imports and uses the useTranslation
hook (or existing t) where the metadata is rendered so localization works at
runtime.

In `@apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx`:
- Around line 909-911: Replace the hardcoded path string in the GraphitiStep
component (GraphitiStep.tsx) with a react-i18next translation key: use the
useTranslation hook and call t('onboarding.graphiti.storagePath', { path:
'~/.aperant/graphs/' }) in place of the literal "Stored in ~/.aperant/graphs/";
also add the matching key "onboarding.graphiti.storagePath": "Stored in
{{path}}" to your en/*.json and fr/*.json locale files so the UI text is
localizable.

In `@apps/desktop/src/shared/i18n/locales/fr/dialogs.json`:
- Line 12: Update the French translation for the initialization failure message
by correcting the elision: locate the JSON key "initFailedDescription" in
dialogs.json and change its value from "Échec de l'initialisation de Aperant.
Veuillez réessayer." to use "d'Aperant" (i.e., "Échec de l'initialisation
d'Aperant. Veuillez réessayer.").

In `@apps/desktop/src/shared/types/project.ts`:
- Around line 223-224: Update the stale comment on the database property:
replace the old default name "auto_claude_memory" with the current canonical
name "aperant_memory" in the comment next to the database?: string declaration
so the documented default matches the rebrand.

In `@CLAUDE.md`:
- Around line 85-90: Update steps 3 and 4 to use the same explicit path prefix
as steps 1-2 so they target the correct files; specifically, change references
to `pr/index.json` and `bot_detection_state.json` to
`.aperant/github/pr/index.json` and `.aperant/github/bot_detection_state.json`
and show the exact reset contents `{"reviews": [], "last_updated": null}` and
`{"reviewed_commits": {}}` respectively.

---

Outside diff comments:
In `@apps/desktop/src/main/ai/config/agent-configs.ts`:
- Around line 477-486: The MCP_SERVER_NAME_MAP is missing the legacy
"auto-claude" alias which mapMcpServerName() still needs to resolve older
configs; add an entry for "auto-claude" mapping to the current server key (e.g.
map "auto-claude" -> "context7") inside MCP_SERVER_NAME_MAP so older
user-provided MCP override strings continue to work and are not silently broken.

In `@apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts`:
- Around line 332-335: The commit message template still uses the old prefix
"auto-claude:"; update the string in the git commit line (the template that
builds `git commit -m "auto-claude: ${subtask.id} -
${subtask.description.slice(0, 50)}"`) to use the new brand prefix "aperant:" so
the commit message becomes `aperant: ${subtask.id} -
${subtask.description.slice(0, 50)}`.

In `@apps/desktop/src/main/ai/runners/__tests__/ideation.test.ts`:
- Around line 284-295: The test for runIdeation names both projectDir and
outputDir but only asserts the projectDir; update the test (using mockStreamText
and inspecting streamArgs.system as systemPrompt) to also assert that the
outputDir is included by adding an expectation that systemPrompt contains the
output path '/my/project/.aperant/ideation' (e.g.,
expect(systemPrompt).toContain('/my/project/.aperant/ideation')); leave the
existing projectDir assertion intact.

In `@apps/desktop/src/main/ipc-handlers/sections/task-section.txt`:
- Around line 778-784: Replace the inline autoBuildDir and specDir path assembly
with the existing getSpecsDir helper to match the pattern used at line 261:
remove the autoBuildDir and path.join usage that builds specDir from
project.autoBuildPath/project.path and task.specId, and instead call
getSpecsDir(...) (the same signature used elsewhere, e.g., getSpecsDir(project,
task.specId) or getSpecsDir(project) plus specId) to obtain the specs directory;
assign specDir from that helper and keep task.specId usage consistent.

In `@apps/desktop/src/main/utils/git-isolation.ts`:
- Around line 166-169: Update the security comment in git-isolation.ts so it
references the current branch naming scheme (`aperant/`) instead of "auto-claude
branch"; specifically edit the exact comment block that starts with "SECURITY:
Use strict exact-match validation..." to mention preventing deletion of another
task's `aperant/` branch and ensure the wording makes clear we must fall back to
the expected `aperant/` pattern when git rev-parse returns an unexpected branch.

In `@apps/desktop/src/main/utils/worktree-cleanup.ts`:
- Around line 132-142: Replace the direct process.platform check with the
centralized platform helper: import and call isWindows() from the platform
utilities and change the condition to if (!isWindows()) around the block that
logs and calls execFileSync('/bin/rm', ['-rf', dirPath], ...); ensure you add
the import for isWindows at the top of the module and keep existing references
to logPrefix and dirPath unchanged so behavior remains the same.

In `@apps/desktop/src/renderer/components/AgentTools.tsx`:
- Around line 1186-1192: Update the stale translation keys in the AgentTools
component: replace t('settings:mcp.servers.autoClaude.name') and
t('settings:mcp.servers.autoClaude.description') with
t('settings:mcp.servers.aperant.name') and
t('settings:mcp.servers.aperant.description') respectively (the surrounding
layout including the always-enabled note t('settings:mcp.alwaysEnabled') stays
unchanged); these strings appear in the Auto-Claude/aperant row in
AgentTools.tsx where the span and paragraph render the name and description.

In `@apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx`:
- Line 118: Replace the outdated branding value "auto_claude_memory" with the
new consistent name (e.g., "aperant_memory") wherever it is used as a default or
placeholder in GraphitiStep.tsx (the database default entry and the placeholder
near the storage path usage), and make the same replacement in the other
referenced components (SecuritySettings.tsx, MemoryBackendSection.tsx) so
defaults, placeholders, and any related keys match the .aperant directory
branding; update any variable names/comments that reference auto_claude_memory
to the new identifier to keep the codebase consistent.

In
`@apps/desktop/src/renderer/components/project-settings/MemoryBackendSection.tsx`:
- Around line 128-145: Replace the hardcoded English strings in
MemoryBackendSection.tsx with react-i18next translation keys: import and call
useTranslation (e.g., const { t } = useTranslation()) at the top of the
component and replace "Database Name", "Name for the memory database (stored in
~/.aperant/memories/)", "Database Path (Optional)", and "Custom storage
location. Default: ~/.aperant/memories/" with t('memory.databaseName'),
t('memory.databaseDescription'), t('memory.databasePathOptional'), and
t('memory.databasePathDescription') (and also translate placeholders like
"auto_claude_memory" and "~/.aperant/memories"); ensure the new keys are added
to the locale resources in the i18n files in a follow-up change.

In `@apps/desktop/src/renderer/components/project-settings/SecuritySettings.tsx`:
- Around line 426-442: In SecuritySettings.tsx, replace the hardcoded
user-facing literals (the paragraph "Stored in ~/.aperant/memories/", the Label
"Database Path (Optional)", the paragraph "Custom storage location. Default:
~/.aperant/memories/", and the two Input placeholders "auto_claude_memory" and
"~/.aperant/memories") with react-i18next keys using useTranslation (e.g.,
t('settings.memoryStored'), t('settings.dbPathLabel'), t('settings.dbPathHelp'),
t('settings.placeholderMemory'), t('settings.placeholderDbPath')) and keep
wiring to envConfig.memoryDatabase and envConfig.memoryDbPath unchanged; then
add corresponding entries to en/settings.json and fr/settings.json with
appropriate translations. Ensure you import and call useTranslation at the top
of SecuritySettings and replace the literal strings with the t(...) calls.

In `@apps/desktop/src/renderer/lib/mocks/project-mock.ts`:
- Around line 9-16: The mock addProject function returns an object whose
autoBuildPath is hardcoded to `${projectPath}/auto-claude`; update this to use
the new canonical folder name `.aperant` by changing the autoBuildPath
generation in addProject to `${projectPath}/.aperant` (keep other fields like
id, name, path and settings using DEFAULT_PROJECT_SETTINGS unchanged) so mock
behavior matches the PR rename.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 08757deb-77fa-4c73-811d-bc301f2da291

📥 Commits

Reviewing files that changed from the base of the PR and between 3f8e16e and f6bf6d4.

📒 Files selected for processing (122)
  • .claude/commands/setup-statusline.md
  • .gitignore
  • CLAUDE.md
  • apps/desktop/prompts/coder.md
  • apps/desktop/prompts/planner.md
  • apps/desktop/prompts/qa_fixer.md
  • apps/desktop/prompts/qa_reviewer.md
  • apps/desktop/src/__tests__/e2e/smoke.test.ts
  • apps/desktop/src/__tests__/integration/rate-limit-subtask-recovery.test.ts
  • apps/desktop/src/__tests__/integration/task-lifecycle.test.ts
  • apps/desktop/src/main/__tests__/file-watcher.test.ts
  • apps/desktop/src/main/__tests__/ipc-handlers.test.ts
  • apps/desktop/src/main/__tests__/project-migration.test.ts
  • apps/desktop/src/main/__tests__/project-store.test.ts
  • apps/desktop/src/main/agent/agent-manager.ts
  • apps/desktop/src/main/agent/agent-process.ts
  • apps/desktop/src/main/agent/agent-queue.ts
  • apps/desktop/src/main/ai/client/__tests__/factory.test.ts
  • apps/desktop/src/main/ai/config/__tests__/agent-configs.test.ts
  • apps/desktop/src/main/ai/config/agent-configs.ts
  • apps/desktop/src/main/ai/context/builder.ts
  • apps/desktop/src/main/ai/context/search.ts
  • apps/desktop/src/main/ai/context/types.ts
  • apps/desktop/src/main/ai/mcp/__tests__/client.test.ts
  • apps/desktop/src/main/ai/mcp/__tests__/registry.test.ts
  • apps/desktop/src/main/ai/mcp/registry.ts
  • apps/desktop/src/main/ai/mcp/types.ts
  • apps/desktop/src/main/ai/memory/graph/incremental-indexer.ts
  • apps/desktop/src/main/ai/merge/file-evolution.ts
  • apps/desktop/src/main/ai/merge/orchestrator.ts
  • apps/desktop/src/main/ai/merge/timeline-tracker.ts
  • apps/desktop/src/main/ai/orchestration/__tests__/qa-loop.test.ts
  • apps/desktop/src/main/ai/orchestration/__tests__/qa-reports.test.ts
  • apps/desktop/src/main/ai/orchestration/__tests__/recovery-manager.test.ts
  • apps/desktop/src/main/ai/orchestration/build-orchestrator.ts
  • apps/desktop/src/main/ai/project/analyzer.ts
  • apps/desktop/src/main/ai/project/project-indexer.ts
  • apps/desktop/src/main/ai/prompts/prompt-loader.ts
  • apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts
  • apps/desktop/src/main/ai/runners/__tests__/commit-message.test.ts
  • apps/desktop/src/main/ai/runners/__tests__/ideation.test.ts
  • apps/desktop/src/main/ai/runners/__tests__/roadmap.test.ts
  • apps/desktop/src/main/ai/runners/commit-message.ts
  • apps/desktop/src/main/ai/runners/github/pr-creator.ts
  • apps/desktop/src/main/ai/runners/ideation.ts
  • apps/desktop/src/main/ai/runners/insights.ts
  • apps/desktop/src/main/ai/runners/roadmap.ts
  • apps/desktop/src/main/ai/security/security-profile.ts
  • apps/desktop/src/main/ai/security/validators/process-validators.ts
  • apps/desktop/src/main/ai/session/__tests__/progress-tracker.test.ts
  • apps/desktop/src/main/ai/tools/__tests__/registry.test.ts
  • apps/desktop/src/main/ai/tools/auto-claude/get-build-progress.ts
  • apps/desktop/src/main/ai/tools/auto-claude/get-session-context.ts
  • apps/desktop/src/main/ai/tools/auto-claude/index.ts
  • apps/desktop/src/main/ai/tools/auto-claude/record-discovery.ts
  • apps/desktop/src/main/ai/tools/auto-claude/record-gotcha.ts
  • apps/desktop/src/main/ai/tools/auto-claude/update-qa-status.ts
  • apps/desktop/src/main/ai/tools/auto-claude/update-subtask-status.ts
  • apps/desktop/src/main/ai/tools/registry.ts
  • apps/desktop/src/main/ai/tools/truncation.ts
  • apps/desktop/src/main/ai/tools/types.ts
  • apps/desktop/src/main/ai/worktree/worktree-manager.ts
  • apps/desktop/src/main/changelog/__tests__/changelog-service.integration.test.ts
  • apps/desktop/src/main/changelog/changelog-service.ts
  • apps/desktop/src/main/config-paths.ts
  • apps/desktop/src/main/insights/paths.ts
  • apps/desktop/src/main/ipc-handlers/README.md
  • apps/desktop/src/main/ipc-handlers/context/utils.ts
  • apps/desktop/src/main/ipc-handlers/env-handlers.ts
  • apps/desktop/src/main/ipc-handlers/github/__tests__/runner-env-handlers.test.ts
  • apps/desktop/src/main/ipc-handlers/github/autofix-handlers.ts
  • apps/desktop/src/main/ipc-handlers/github/pr-handlers.ts
  • apps/desktop/src/main/ipc-handlers/github/triage-handlers.ts
  • apps/desktop/src/main/ipc-handlers/gitlab/autofix-handlers.ts
  • apps/desktop/src/main/ipc-handlers/gitlab/mr-review-handlers.ts
  • apps/desktop/src/main/ipc-handlers/gitlab/triage-handlers.ts
  • apps/desktop/src/main/ipc-handlers/project-handlers.ts
  • apps/desktop/src/main/ipc-handlers/sections/task-section.txt
  • apps/desktop/src/main/ipc-handlers/sections/task_extracted.txt
  • apps/desktop/src/main/ipc-handlers/task/__tests__/logs-integration.test.ts
  • apps/desktop/src/main/ipc-handlers/task/__tests__/worktree-branch-validation.test.ts
  • apps/desktop/src/main/ipc-handlers/task/crud-handlers.ts
  • apps/desktop/src/main/ipc-handlers/task/execution-handlers.ts
  • apps/desktop/src/main/ipc-handlers/task/worktree-handlers.ts
  • apps/desktop/src/main/ipc-handlers/terminal/worktree-handlers.ts
  • apps/desktop/src/main/project-initializer.ts
  • apps/desktop/src/main/project-store.ts
  • apps/desktop/src/main/release-service.ts
  • apps/desktop/src/main/services/profile/profile-manager.test.ts
  • apps/desktop/src/main/services/profile/profile-manager.ts
  • apps/desktop/src/main/task-log-service.ts
  • apps/desktop/src/main/utils/git-isolation.ts
  • apps/desktop/src/main/utils/profile-manager.test.ts
  • apps/desktop/src/main/utils/profile-manager.ts
  • apps/desktop/src/main/utils/spec-number-lock.ts
  • apps/desktop/src/main/utils/spec-path-helpers.ts
  • apps/desktop/src/main/utils/worktree-cleanup.ts
  • apps/desktop/src/main/worktree-paths.ts
  • apps/desktop/src/preload/api/project-api.ts
  • apps/desktop/src/renderer/App.tsx
  • apps/desktop/src/renderer/__tests__/project-store-tabs.test.ts
  • apps/desktop/src/renderer/components/AgentTools.tsx
  • apps/desktop/src/renderer/components/__tests__/ProjectTabBar.test.tsx
  • apps/desktop/src/renderer/components/__tests__/SortableProjectTab.test.tsx
  • apps/desktop/src/renderer/components/context/MemoriesTab.tsx
  • apps/desktop/src/renderer/components/github-prs/components/PRDetail.tsx
  • apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx
  • apps/desktop/src/renderer/components/project-settings/MemoryBackendSection.tsx
  • apps/desktop/src/renderer/components/project-settings/SecuritySettings.tsx
  • apps/desktop/src/renderer/components/task-detail/task-review/CreatePRDialog.test.tsx
  • apps/desktop/src/renderer/lib/mocks/infrastructure-mock.ts
  • apps/desktop/src/renderer/lib/mocks/project-mock.ts
  • apps/desktop/src/renderer/stores/project-store.ts
  • apps/desktop/src/shared/constants/config.ts
  • apps/desktop/src/shared/constants/ipc.ts
  • apps/desktop/src/shared/i18n/locales/en/dialogs.json
  • apps/desktop/src/shared/i18n/locales/en/settings.json
  • apps/desktop/src/shared/i18n/locales/fr/dialogs.json
  • apps/desktop/src/shared/i18n/locales/fr/settings.json
  • apps/desktop/src/shared/types/ipc.ts
  • apps/desktop/src/shared/types/project.ts
  • apps/desktop/src/shared/types/terminal.ts

Comment on lines +124 to 126
1. Check if `.aperant-status` exists in your project root
2. Verify the path to `statusline.py` is correct
3. Try running the command manually: `python auto-claude/statusline.py --format compact`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use one canonical path name throughout this guide.

Line 124 moved to .aperant-status, but Lines 126/139/145/150 still instruct auto-claude/statusline.py. This mixed naming creates a broken/ambiguous setup path for users.

Proposed doc fix
-3. Try running the command manually: `python auto-claude/statusline.py --format compact`
+3. Try running the command manually: `python aperant/statusline.py --format compact`
...
-python auto-claude/statusline.py --format compact
+python aperant/statusline.py --format compact
...
-python auto-claude/statusline.py --format compact --spec 001-my-feature
+python aperant/statusline.py --format compact --spec 001-my-feature
...
-python ~/projects/my-app/auto-claude/statusline.py --format compact --project-dir ~/projects/my-app
+python ~/projects/my-app/aperant/statusline.py --format compact --project-dir ~/projects/my-app

Also applies to: 139-150

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.claude/commands/setup-statusline.md around lines 124 - 126, The guide
currently mixes two path names — `.aperant-status` and
`auto-claude/statusline.py` — causing ambiguity; pick one canonical path (e.g.,
`.aperant-status/statusline.py` or `auto-claude/statusline.py`) and update all
occurrences in the document so they match consistently (references in the
checklist, the "Try running the command" example, and the later steps around
lines 139–150). Search for strings `.aperant-status` and
`auto-claude/statusline.py` and replace them with the chosen canonical path in
the setup-statusline.md content, and ensure the example command (the `python ...
--format compact` line) and any path-verification steps reference that same
canonical path.

Comment on lines 144 to 147
function setupTestProject(): void {
mkdirSync(TEST_PROJECT_PATH, { recursive: true });
mkdirSync(path.join(TEST_PROJECT_PATH, "auto-claude", "specs"), { recursive: true });
mkdirSync(path.join(TEST_PROJECT_PATH, "aperant", "specs"), { recursive: true });
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix the .aperant fixture path.

setupTestProject() creates aperant/specs without the leading dot, so this shared fixture no longer matches the directory name the handlers detect. That weakens the baseline setup and can hide regressions in initialized-project detection.

🛠️ Proposed fix
 function setupTestProject(): void {
   mkdirSync(TEST_PROJECT_PATH, { recursive: true });
-  mkdirSync(path.join(TEST_PROJECT_PATH, "aperant", "specs"), { recursive: true });
+  mkdirSync(path.join(TEST_PROJECT_PATH, ".aperant", "specs"), { recursive: true });
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/__tests__/ipc-handlers.test.ts` around lines 144 - 147,
The fixture directory created in setupTestProject() is missing the leading dot
so tests create "aperant/specs" instead of ".aperant/specs"; update
setupTestProject() to create the hidden directory (use
path.join(TEST_PROJECT_PATH, ".aperant", "specs") with mkdirSync and {
recursive: true }) so the TEST_PROJECT_PATH fixture matches the handlers'
expected ".aperant" directory and preserves initialized-project detection.

Comment on lines +289 to 292
'aperant': {
name: 'Aperant Tools',
description: 'Build progress tracking, session context, discoveries & gotchas recording',
icon: ListChecks,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Do not add new hardcoded user-facing MCP strings in TSX.

name and description for the new aperant server are English literals and will bypass localization.

Suggested refactor (translation-key based server metadata)
-const MCP_SERVERS: Record<string, { name: string; description: string; icon: React.ElementType; tools?: string[] }> = {
+const MCP_SERVERS: Record<string, { nameKey: string; descriptionKey: string; icon: React.ElementType; tools?: string[] }> = {
   ...
   'aperant': {
-    name: 'Aperant Tools',
-    description: 'Build progress tracking, session context, discoveries & gotchas recording',
+    nameKey: 'settings:mcp.servers.aperant.name',
+    descriptionKey: 'settings:mcp.servers.aperant.description',
     icon: ListChecks,
     tools: [
       ...
     ],
   },
-<span className="font-medium">{serverInfo?.name || server}</span>
+<span className="font-medium">{serverInfo ? t(serverInfo.nameKey) : server}</span>
-<div className="text-xs text-muted-foreground">{server?.description}</div>
+<div className="text-xs text-muted-foreground">
+  {server ? t(server.descriptionKey) : ''}
+</div>

As per coding guidelines, apps/desktop/src/renderer/**/*.{tsx,jsx}: “All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users. Add keys to both en/*.json and fr/*.json translation files.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/AgentTools.tsx` around lines 289 - 292,
The new 'aperant' entry in AgentTools (object key 'aperant' with properties name
and description in AgentTools.tsx) uses hardcoded English strings; replace those
literals with react-i18next translation keys (e.g. t('servers.aperant.name') and
t('servers.aperant.description') inside the component where ListChecks is
already used), then add corresponding entries for servers.aperant.name and
servers.aperant.description to both the en/*.json and fr/*.json translation
files; ensure the code imports and uses the useTranslation hook (or existing t)
where the metadata is rendered so localization works at runtime.

Comment on lines 909 to 911
<p className="text-xs text-muted-foreground">
Stored in ~/.auto-claude/graphs/
Stored in ~/.aperant/graphs/
</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Hardcoded user-facing string violates i18n guidelines.

The path text should use a react-i18next translation key instead of a hardcoded string to support localization.

🌐 Proposed fix using translation key
 <p className="text-xs text-muted-foreground">
-  Stored in ~/.aperant/graphs/
+  {t('onboarding.graphiti.storagePath', { path: '~/.aperant/graphs/' })}
 </p>

Add the translation key to both en/*.json and fr/*.json:

{
  "onboarding": {
    "graphiti": {
      "storagePath": "Stored in {{path}}"
    }
  }
}

As per coding guidelines: "All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<p className="text-xs text-muted-foreground">
Stored in ~/.auto-claude/graphs/
Stored in ~/.aperant/graphs/
</p>
<p className="text-xs text-muted-foreground">
{t('onboarding.graphiti.storagePath', { path: '~/.aperant/graphs/' })}
</p>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/onboarding/GraphitiStep.tsx` around
lines 909 - 911, Replace the hardcoded path string in the GraphitiStep component
(GraphitiStep.tsx) with a react-i18next translation key: use the useTranslation
hook and call t('onboarding.graphiti.storagePath', { path: '~/.aperant/graphs/'
}) in place of the literal "Stored in ~/.aperant/graphs/"; also add the matching
key "onboarding.graphiti.storagePath": "Stored in {{path}}" to your en/*.json
and fr/*.json locale files so the UI text is localizable.

"sourcePathNotConfiguredDescription": "Veuillez définir le chemin source Aperant dans les paramètres de l'application avant d'initialiser.",
"initFailed": "Échec de l'initialisation",
"initFailedDescription": "Échec de l'initialisation de Aperant. Veuillez réessayer."
"initFailedDescription": "Échec de l'initialisation de Aperant. Veuillez réessayer.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix French grammar in initialization failure message.

Line [12] should use elision: d'Aperant instead of de Aperant.

✏️ Suggested fix
-    "initFailedDescription": "Échec de l'initialisation de Aperant. Veuillez réessayer.",
+    "initFailedDescription": "Échec de l'initialisation d'Aperant. Veuillez réessayer.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"initFailedDescription": "Échec de l'initialisation de Aperant. Veuillez réessayer.",
"initFailedDescription": "Échec de l'initialisation d'Aperant. Veuillez réessayer.",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/i18n/locales/fr/dialogs.json` at line 12, Update the
French translation for the initialization failure message by correcting the
elision: locate the JSON key "initFailedDescription" in dialogs.json and change
its value from "Échec de l'initialisation de Aperant. Veuillez réessayer." to
use "d'Aperant" (i.e., "Échec de l'initialisation d'Aperant. Veuillez
réessayer.").

Comment on lines 223 to +224
database?: string; // Database name (default: auto_claude_memory)
dbPath?: string; // Database storage path (default: ~/.auto-claude/memories)
dbPath?: string; // Database storage path (default: ~/.aperant/memories)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Update stale default database-name comment for rebrand consistency.

Line 223 still documents auto_claude_memory as default while this PR standardizes naming to aperant. Please align this comment with the current canonical naming to avoid config/documentation drift.

Suggested doc-only fix
-  database?: string;  // Database name (default: auto_claude_memory)
+  database?: string;  // Database name (default: aperant_memory)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
database?: string; // Database name (default: auto_claude_memory)
dbPath?: string; // Database storage path (default: ~/.auto-claude/memories)
dbPath?: string; // Database storage path (default: ~/.aperant/memories)
database?: string; // Database name (default: aperant_memory)
dbPath?: string; // Database storage path (default: ~/.aperant/memories)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/types/project.ts` around lines 223 - 224, Update the
stale comment on the database property: replace the old default name
"auto_claude_memory" with the current canonical name "aperant_memory" in the
comment next to the database?: string declaration so the documented default
matches the rebrand.

Comment on lines +85 to 90
To fully clear all PR review data so reviews run fresh, delete/reset these three things in `.aperant/github/`:

1. `rm .auto-claude/github/pr/logs_*.json` — review log files
2. `rm .auto-claude/github/pr/review_*.json` — review result files
1. `rm .aperant/github/pr/logs_*.json` — review log files
2. `rm .aperant/github/pr/review_*.json` — review result files
3. Reset `pr/index.json` to `{"reviews": [], "last_updated": null}`
4. Reset `bot_detection_state.json` to `{"reviewed_commits": {}}` — this is the gatekeeper; without clearing it, the bot detector skips already-seen commits
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use full paths consistently in reset steps 3-4.

In the same instruction block, steps 1-2 use explicit .aperant/github/... paths but steps 3-4 switch to relative names. Please make 3-4 explicit too to avoid targeting the wrong files.

Suggested doc patch
-3. Reset `pr/index.json` to `{"reviews": [], "last_updated": null}`
-4. Reset `bot_detection_state.json` to `{"reviewed_commits": {}}` — this is the gatekeeper; without clearing it, the bot detector skips already-seen commits
+3. Reset `.aperant/github/pr/index.json` to `{"reviews": [], "last_updated": null}`
+4. Reset `.aperant/github/bot_detection_state.json` to `{"reviewed_commits": {}}` — this is the gatekeeper; without clearing it, the bot detector skips already-seen commits
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
To fully clear all PR review data so reviews run fresh, delete/reset these three things in `.aperant/github/`:
1. `rm .auto-claude/github/pr/logs_*.json` — review log files
2. `rm .auto-claude/github/pr/review_*.json` — review result files
1. `rm .aperant/github/pr/logs_*.json` — review log files
2. `rm .aperant/github/pr/review_*.json` — review result files
3. Reset `pr/index.json` to `{"reviews": [], "last_updated": null}`
4. Reset `bot_detection_state.json` to `{"reviewed_commits": {}}` — this is the gatekeeper; without clearing it, the bot detector skips already-seen commits
To fully clear all PR review data so reviews run fresh, delete/reset these three things in `.aperant/github/`:
1. `rm .aperant/github/pr/logs_*.json` — review log files
2. `rm .aperant/github/pr/review_*.json` — review result files
3. Reset `.aperant/github/pr/index.json` to `{"reviews": [], "last_updated": null}`
4. Reset `.aperant/github/bot_detection_state.json` to `{"reviewed_commits": {}}` — this is the gatekeeper; without clearing it, the bot detector skips already-seen commits
🧰 Tools
🪛 LanguageTool

[uncategorized] ~85-~85: The official name of this software platform is spelled with a capital “H”.
Context: ...esh, delete/reset these three things in .aperant/github/: 1. `rm .aperant/github/pr/logs_*.js...

(GITHUB)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 85 - 90, Update steps 3 and 4 to use the same
explicit path prefix as steps 1-2 so they target the correct files;
specifically, change references to `pr/index.json` and
`bot_detection_state.json` to `.aperant/github/pr/index.json` and
`.aperant/github/bot_detection_state.json` and show the exact reset contents
`{"reviews": [], "last_updated": null}` and `{"reviewed_commits": {}}`
respectively.

Continues the rename initiated in 18453ad. Updates all remaining
references in tools, components, handlers, types, tests, and docs
from auto-claude/AutoBuild to aperant/Aperant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
};
// lgtm[js/http-to-file-access] - specDir is controlled, Linear data sanitized
writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2), 'utf-8');
writeFileSync(path.join(specDir, APERANT_PATHS.IMPLEMENTATION_PLAN), JSON.stringify(implementationPlan, null, 2), 'utf-8');

Check warning

Code scanning / CodeQL

Network data written to file Medium

Write to file system depends on
Untrusted data
.
};
// lgtm[js/http-to-file-access] - specDir is controlled, Linear data sanitized
writeFileSync(path.join(specDir, AUTO_BUILD_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2), 'utf-8');
writeFileSync(path.join(specDir, APERANT_PATHS.REQUIREMENTS), JSON.stringify(requirements, null, 2), 'utf-8');

Check warning

Code scanning / CodeQL

Network data written to file Medium

Write to file system depends on
Untrusted data
.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 4 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

function setupTestProject(): void {
mkdirSync(TEST_PROJECT_PATH, { recursive: true });
mkdirSync(path.join(TEST_PROJECT_PATH, "auto-claude", "specs"), { recursive: true });
mkdirSync(path.join(TEST_PROJECT_PATH, "aperant", "specs"), { recursive: true });
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test setup creates wrong directory path without dot prefix

Medium Severity

The setupTestProject() function creates aperant/specs (no dot prefix) but getAperantPath() only checks for .aperant (with dot). When tests call addProject(), the project won't be detected as initialized because the directory name doesn't match. Other tests in this same file correctly use ".aperant" (e.g., lines 423, 493), confirming the dot prefix is required.

Fix in Cursor Fix in Web

'.next', '.nuxt', 'target', 'vendor', '.idea', '.vscode', 'auto-claude',
'.auto-claude', '.pytest_cache', '.mypy_cache', 'coverage', '.turbo', '.cache',
'.next', '.nuxt', 'target', 'vendor', '.idea', '.vscode',
'.aperant', '.pytest_cache', '.mypy_cache', 'coverage', '.turbo', '.cache',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SKIP_DIRS dropped .auto-claude breaking unmigrated project searches

Low Severity

The old SKIP_DIRS set contained both auto-claude and .auto-claude. The new set only contains .aperant, dropping .auto-claude entirely. Projects that haven't yet been migrated (still have .auto-claude/ data directories) will now have those directories searched, potentially causing slow searches and irrelevant results from spec/plan metadata files.

Fix in Cursor Fix in Web

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 43

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (12)
apps/desktop/src/renderer/components/AddProjectModal.tsx (1)

121-121: ⚠️ Potential issue | 🟡 Minor

Hardcoded error string violates i18n requirements.

The fallback string 'Failed to create project folder' should use a translation key for localization consistency. As per coding guidelines, all frontend user-facing text must use react-i18next translation keys.

🌐 Proposed fix
-        setError(result.error || 'Failed to create project folder');
+        setError(result.error || t('addProject.failedToCreate'));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/AddProjectModal.tsx` at line 121, The
hardcoded fallback in setError(result.error || 'Failed to create project
folder') violates i18n rules; replace the literal with a translation lookup (use
the component's i18n hook: e.g. t('projects.createFailed') or an existing key)
and ensure useTranslation is imported/used in AddProjectModal.tsx if not already
present; keep result.error when present, but call setError(result.error ||
t('projects.createFailed')) so the UI uses a translation key for the default
message.
apps/desktop/src/renderer/components/WelcomeScreen.tsx (1)

104-108: ⚠️ Potential issue | 🟡 Minor

Hardcoded string "Initialized" breaks localization.

Line 106 contains a hardcoded English string which violates the coding guideline requiring all frontend user-facing text to use react-i18next translation keys. The rest of this component correctly uses the t() function.

🌐 Proposed fix to use translation key
 {project.aperantPath && (
   <span className="text-[10px] px-1.5 py-0.5 rounded-full bg-success/20 text-success shrink-0">
-    Initialized
+    {t('welcome:recentProjects.initialized')}
   </span>
 )}

Add the key to both translation files:

en/welcome.json:

"recentProjects": {
  ...
  "initialized": "Initialized"
}

fr/welcome.json:

"recentProjects": {
  ...
  "initialized": "Initialisé"
}

As per coding guidelines: "All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/WelcomeScreen.tsx` around lines 104 -
108, Replace the hardcoded "Initialized" string in WelcomeScreen.tsx with a
react-i18next lookup (use the t function) — specifically change the span that
renders when project.aperantPath to call t('recentProjects.initialized') instead
of the literal; then add the key "recentProjects.initialized": "Initialized" to
the English translation file and "recentProjects.initialized": "Initialisé" to
the French translation file so both locales are covered.
apps/desktop/src/main/utils/git-isolation.ts (1)

50-52: ⚠️ Potential issue | 🟡 Minor

Inconsistent naming: "Auto-Claude" reference remains in comment.

The comment on line 51 still references "Auto-Claude manages commits" while this PR renames all references to "Aperant". This should be updated for consistency.

📝 Proposed fix
  * Also sets HUSKY=0 to disable the user's pre-commit hooks when
- * Auto-Claude manages commits, preventing double-hook execution
+ * Aperant manages commits, preventing double-hook execution
  * and potential conflicts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/utils/git-isolation.ts` around lines 50 - 52, Update
the inline comment that currently reads "Auto-Claude manages commits" to use the
new product name "Aperant" for consistency; specifically change the sentence
that mentions HUSKY=0 disabling the user's pre-commit hooks so it reads that
HUSKY=0 is set when "Aperant manages commits", leaving the surrounding text
(including the HUSKY=0 reference) unchanged.
apps/desktop/src/main/ipc-handlers/changelog-handlers.ts.bk (1)

1-264: ⚠️ Potential issue | 🟠 Major

Remove backup file from the repository.

This .bk file appears to be an accidentally committed backup and should be deleted. Backup files should be excluded via .gitignore to prevent accidental commits.

#!/bin/bash
# Check if there are other backup files accidentally committed
fd -e bk -e bak -e orig -e backup
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/changelog-handlers.ts.bk` around lines 1 -
264, Delete the accidentally committed backup file that contains the duplicate
registerChangelogHandlers implementation (the .bk file); remove it from the
repository (git rm) and update .gitignore to exclude common backup extensions
(bk, bak, orig, backup) so future backups aren’t committed, and ensure the
canonical changelog handler implementation (function registerChangelogHandlers)
remains in the repo.
apps/desktop/src/renderer/components/GitHubSetupModal.tsx (2)

747-748: ⚠️ Potential issue | 🟡 Minor

Use translation key instead of hardcoded text.

This user-facing description text is hardcoded in English, breaking localization for non-English users. As per coding guidelines, all frontend user-facing text in renderer components must use react-i18next translation keys. Add a key to both en/*.json and fr/*.json translation files.

🌐 Suggested fix using translation key
 <DialogDescription>
-  Choose which branch Aperant should use as the base for creating task branches.
+  {t('githubSetup.branchSelectionDescription')}
 </DialogDescription>

Then add to translation files:

// en/dialogs.json
"githubSetup": {
  "branchSelectionDescription": "Choose which branch Aperant should use as the base for creating task branches."
}

// fr/dialogs.json
"githubSetup": {
  "branchSelectionDescription": "Choisissez la branche qu'Aperant doit utiliser comme base pour créer les branches de tâches."
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/GitHubSetupModal.tsx` around lines 747 -
748, Replace the hardcoded English description inside GitHubSetupModal (the
DialogDescription element) with a react-i18next translation key; use the
component's i18n instance (e.g., t('githubSetup.branchSelectionDescription'))
where DialogDescription currently contains the literal string. Add the
corresponding key "githubSetup.branchSelectionDescription" with the provided
English and French values to the renderer translation files (en/dialogs.json and
fr/dialogs.json). Ensure the component imports and uses the useTranslation hook
if not already present and update any tests or snapshot text if necessary.

798-804: ⚠️ Potential issue | 🟡 Minor

Use translation key with interpolation for help text.

This user-facing help text is hardcoded in English. The text should use a translation key that supports interpolation for the branch example and selected branch name.

🌐 Suggested fix using translation key with interpolation
 <p className="text-xs text-muted-foreground">
-  All tasks will be created from branches like{' '}
-  <code className="px-1 bg-muted rounded">aperant/task-name</code>
-  {selectedBranch && (
-    <> based on <code className="px-1 bg-muted rounded">{selectedBranch}</code></>
-  )}
+  {t('githubSetup.branchPatternHelp', {
+    pattern: 'aperant/task-name',
+    baseBranch: selectedBranch
+  })}
 </p>

Then add to translation files with proper handling of code elements:

// en/dialogs.json
"githubSetup": {
  "branchPatternHelp": "All tasks will be created from branches like <code>{{pattern}}</code>{{baseBranch, ' based on <code>{{baseBranch}}</code>'}}"
}

Note: You may need to use Trans component from react-i18next for proper HTML rendering of <code> elements.

As per coding guidelines, all frontend user-facing text must use react-i18next translation keys. Add keys to both en/*.json and fr/*.json translation files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/GitHubSetupModal.tsx` around lines 798 -
804, The help text in GitHubSetupModal (the paragraph containing the branch
pattern and selectedBranch) is hardcoded; replace it with a react-i18next
translation key (e.g., "githubSetup.branchPatternHelp") that supports
interpolation and HTML/code elements using the Trans component, passing pattern
and selectedBranch as interpolation variables (use selectedBranch only when
present); add the corresponding key to en and fr translation JSON files
(ensuring markup for <code> is preserved or handled via Trans) and update the
component to render Trans with values={{ pattern: 'aperant/task-name',
baseBranch: selectedBranch }} so the branch example and optional "based on"
segment are localized and properly interpolated.
apps/desktop/src/main/utils/spec-number-lock.ts (1)

150-167: ⚠️ Potential issue | 🟠 Major

Replace hardcoded .aperant with variable to match dynamic path handling in main specs scan.

Line 157 hardcodes .aperant while line 153 respects the specsBase variable. If aperantPath ever differs from the default (via initialization or updates), worktree specs scanning will fail. Use the same variable reference for consistency.

💡 Proposed fix
     const specsBase = aperantPath || '.aperant';

     // 1. Scan main project specs
     const mainSpecsDir = path.join(this.projectDir, specsBase, 'specs');
     maxNumber = Math.max(maxNumber, this.scanSpecsDir(mainSpecsDir));

     // 2. Scan all worktree specs
-    const worktreesDir = path.join(this.projectDir, '.aperant', 'worktrees', 'tasks');
+    const worktreesDir = path.join(this.projectDir, specsBase, 'worktrees', 'tasks');
     if (existsSync(worktreesDir)) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/utils/spec-number-lock.ts` around lines 150 - 167, The
worktree scan uses a hardcoded '.aperant' path while the initial main specs scan
uses the dynamic specsBase variable; update the worktree path construction to
use specsBase instead of the literal '.aperant' so worktreeDir and
worktreeSpecsDir are built consistently (replace occurrences that join
'.aperant' with specsBase in the code around scanSpecsDir, worktreesDir and
worktreeSpecsDir where variables like specsBase, worktreesDir, scanSpecsDir and
worktree.name are used).
apps/desktop/src/main/ipc-handlers/task/crud-handlers.ts (1)

175-195: ⚠️ Potential issue | 🟠 Major

Use the global spec-number allocator here too.

This scan only inspects the main specs directory. The store already supports worktree-only specs, so a higher-numbered task that only exists in a worktree can be missed and this handler can reuse its number. Reuse the same global numbering strategy as ideation/task-converter.ts here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/task/crud-handlers.ts` around lines 175 -
195, The handler currently computes specNumber by scanning only the main
specsDir (using getSpecsDir and the existingDirs/existingNumbers logic), which
can clash with worktree-only specs; replace that local directory-only allocation
with the global spec-number allocator used in ideation/task-converter.ts: import
and call the allocator (the function exported by ideation/task-converter.ts that
returns the next global spec number) to set specNumber instead of the
existingDirs -> existingNumbers logic, and remove or fall back from the local
scan (the block that computes existingDirs, existingNumbers, and sets
specNumber) so the handler uses the same global numbering strategy as the rest
of the app.
apps/desktop/src/main/ipc-handlers/insights-handlers.ts (1)

81-84: ⚠️ Potential issue | 🟡 Minor

Remove console.log statements from production code.

Per coding guidelines, console.log output is invisible in bundled Electron apps. These debug statements should be removed or replaced with proper observability tooling.

🛠️ Suggested fix
-      console.log("[Insights Handler] Using model config:", {
-        model: configWithSettings.model,
-        thinkingLevel: configWithSettings.thinkingLevel,
-      });

As per coding guidelines: "Do not use console.log in production code. console.log output is invisible in bundled Electron apps."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/insights-handlers.ts` around lines 81 -
84, Remove the console.log call in the Insights handler that prints
configWithSettings.model and configWithSettings.thinkingLevel; instead use the
application's structured logging facility (e.g., replace with
processLogger.debug/processLogger.info or the project's main logger) or drop the
debug entirely so no console logging remains in production. Update the code
referencing configWithSettings.model and configWithSettings.thinkingLevel in the
same block (the console.log shown) to call the chosen logger with a descriptive
message and include the values as structured fields rather than using
console.log.
apps/desktop/src/renderer/components/project-settings/GeneralSettings.tsx (2)

20-25: 🛠️ Refactor suggestion | 🟠 Major

Use @shared/* in this touched import block.

These ../../../shared/* imports make the component brittle to moves/renames. Please switch this block to the repo’s shared path aliases while you’re touching it.

♻️ Suggested change
-import { AVAILABLE_MODELS } from '../../../shared/constants';
+import { AVAILABLE_MODELS } from '@shared/constants';
 import type {
   Project,
   ProjectSettings as ProjectSettingsType,
   AperantVersionInfo
-} from '../../../shared/types';
+} from '@shared/types';

As per coding guidelines: apps/desktop/src/**/*.{ts,tsx}: Use path aliases defined in tsconfig.json for imports: @/* (renderer), @shared/* (shared), @preload/* (preload), @features/*, @components/*, @hooks/*, @lib/*.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/project-settings/GeneralSettings.tsx`
around lines 20 - 25, The import block in GeneralSettings.tsx uses relative
paths ('../../../shared/constants' and '../../../shared/types') which are
brittle; replace those with the shared path alias imports using `@shared` — e.g.
import { AVAILABLE_MODELS } from '@shared/constants' and import the types
Project, ProjectSettings (as ProjectSettingsType), AperantVersionInfo from
'@shared/types' — update the import statements referencing AVAILABLE_MODELS,
Project, ProjectSettingsType, and AperantVersionInfo accordingly so the
component uses the tsconfig path alias `@shared/`*.

50-76: ⚠️ Potential issue | 🟠 Major

Localize the new Aperant copy.

This block adds new English text directly in JSX even though the component already uses useTranslation. Move the new heading/help/button text into settings keys and add matching entries in both locales.

As per coding guidelines: apps/desktop/src/renderer/**/*.{tsx,jsx}: All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users. Add keys to both en/*.json and fr/*.json translation files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/project-settings/GeneralSettings.tsx`
around lines 50 - 76, The new hardcoded strings in GeneralSettings.tsx (heading
"Aperant Integration", "Not Initialized", helper copy "Initialize Aperant to
enable task creation and agent workflows.", and button labels "Initializing..."
/ "Initialize Aperant") must be replaced with react-i18next keys from the
settings namespace; update the JSX to use t('settings.aperant.title'),
t('settings.aperant.statusNotInitialized'), t('settings.aperant.help'), and
t('settings.aperant.initializeButton' / 'settings.aperant.initializing') (or
similar) and keep using existing handlers like handleInitialize and isUpdating;
then add the corresponding entries under the settings section in both locales
(en JSON and fr JSON) so both languages have these new keys.
apps/desktop/src/shared/constants/config.ts (1)

98-119: ⚠️ Potential issue | 🟡 Minor

Remove the unused MEMORY_STATE constant or update its path to match the documented .aperant/ structure.

APERANT_PATHS.MEMORY_STATE appears to be dead code. A codebase search shows it's never referenced anywhere, while memory state is actually managed via getMemoriesDir() in config-paths.ts, which correctly handles migration from .auto-claude/memories to .aperant/memories. Either remove the constant or, if retained for backward compatibility, update it to '.aperant/.memory_state.json' and add a comment explaining its purpose.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/constants/config.ts` around lines 98 - 119,
APERANT_PATHS currently defines MEMORY_STATE as '.memory_state.json' but it's
unused and inconsistent with the documented .aperant/ layout; either remove
APERANT_PATHS.MEMORY_STATE or update it to '.aperant/.memory_state.json' and add
a short comment explaining it's kept for backward compatibility and that real
memory handling is done via getMemoriesDir() in config-paths.ts (which migrates
from .auto-claude/memories to .aperant/memories); modify the APERANT_PATHS
object accordingly and run a code search to ensure no references break.
♻️ Duplicate comments (7)
apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts (1)

107-109: ⚠️ Potential issue | 🟡 Minor

Missing dot prefix on folder name creates path inconsistency.

The fallback path uses ./aperant/specs/... but the canonical data folder is .aperant (hidden folder with dot prefix), as used in the WORKTREE_PATH_PATTERNS above. This inconsistency could cause spec files to reference an incorrect location.

🐛 Proposed fix
   // Fallback: just use the spec dir name
   const parts = resolvedSpec.split(/[/\\]/);
-  return `./aperant/specs/${parts[parts.length - 1]}`;
+  return `./.aperant/specs/${parts[parts.length - 1]}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts` around lines
107 - 109, The fallback return path uses the wrong folder name; change the
fallback in the subtask path generator so it returns the hidden canonical folder
`.aperant` instead of `aperant`—locate the code that builds the fallback from
resolvedSpec (the const parts = resolvedSpec.split(/[/\\]/); and the return
statement) and update the returned string to use
`./.aperant/specs/${parts[parts.length - 1]}` to match WORKTREE_PATH_PATTERNS
and ensure consistent spec file resolution.
apps/desktop/src/main/ipc-handlers/task/worktree-handlers.ts (1)

2702-2703: ⚠️ Potential issue | 🟠 Major

Use the configured specs dir for orphan detection.

mainSpecsDir is still hardcoded to .aperant/specs. If a project stores specs under a non-default aperantPath, taskLookupSuccessful can flip to true even when the task cache lookup actually failed, and healthy worktrees will be surfaced as orphaned.

Minimal fix
-        const mainSpecsDir = path.join(project.path, '.aperant', 'specs');
+        const mainSpecsDir = path.join(project.path, getSpecsDir(project.aperantPath));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/task/worktree-handlers.ts` around lines
2702 - 2703, The orphan-detection uses a hardcoded mainSpecsDir; replace it so
it joins the project's configured aperant path instead of the literal ".aperant"
(e.g. compute mainSpecsDir using project.aperantPath or the project's configured
aperant path with a fallback to ".aperant" and then 'specs') so
taskLookupSuccessful is based on the real specs location; update the code that
sets mainSpecsDir and keep the subsequent taskLookupSuccessful calculation
unchanged (look for mainSpecsDir and taskLookupSuccessful in
worktree-handlers.ts).
apps/desktop/src/main/ipc-handlers/sections/task-section.txt (1)

261-263: ⚠️ Potential issue | 🟠 Major

Consolidate spec-dir resolution to getSpecsDir(project.aperantPath) everywhere.

These updated paths still use inline fallback + 'specs', which can drift from the helper-based resolution used elsewhere in this handler.

🔧 Proposed refactor pattern
-const aperantDir = project.aperantPath || '.aperant';
-const specDir = path.join(project.path, aperantDir, 'specs', task.specId);
+const specsBaseDir = getSpecsDir(project.aperantPath);
+const specDir = path.join(project.path, specsBaseDir, task.specId);

Also applies to: 778-783, 1210-1210

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/sections/task-section.txt` around lines
261 - 263, The inline spec-dir resolution using aperantDir and path.join (the
variables aperantDir and specDir) should be replaced with the centralized helper
getSpecsDir(project.aperantPath) to avoid drift; update every occurrence
(including the shown block and the other instances around lines referenced) to
call getSpecsDir(project.aperantPath) and use its return value instead of
computing aperantDir || '.aperant' and appending 'specs' manually so all spec
directory resolution is consistent across this handler.
apps/desktop/src/main/agent/agent-manager.ts (1)

378-378: ⚠️ Potential issue | 🟠 Major

Use getSpecsDir() for all fallback spec paths (not hardcoded .aperant/specs).

resolvedSpecDir and restart-time planPath bypass project-specific specs resolution, which can target the wrong directory when aperantPath differs.

🔧 Proposed fix
-    const resolvedSpecDir = specDir ?? path.join(projectPath, '.aperant', 'specs', taskId);
+    const project = projectStore.getProjects().find((p) => p.id === projectId || p.path === projectPath);
+    const specsBaseDir = getSpecsDir(project?.aperantPath);
+    const resolvedSpecDir = specDir ?? path.join(projectPath, specsBaseDir, taskId);
-        const planPath = context.specDir
-          ? path.join(context.specDir, APERANT_PATHS.IMPLEMENTATION_PLAN)
-          : path.join(context.projectPath, APERANT_PATHS.SPECS_DIR, context.specId, APERANT_PATHS.IMPLEMENTATION_PLAN);
+        const restartProject = context.projectId
+          ? projectStore.getProject(context.projectId)
+          : projectStore.getProjects().find((p) => p.path === context.projectPath);
+        const specsBaseDir = getSpecsDir(restartProject?.aperantPath);
+        const planPath = context.specDir
+          ? path.join(context.specDir, APERANT_PATHS.IMPLEMENTATION_PLAN)
+          : path.join(context.projectPath, specsBaseDir, context.specId, APERANT_PATHS.IMPLEMENTATION_PLAN);

Also applies to: 823-825

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/agent/agent-manager.ts` at line 378, resolvedSpecDir is
using a hardcoded fallback path (path.join(projectPath, '.aperant', 'specs',
taskId)) which bypasses project-specific resolution; replace that fallback with
a call to the central resolver getSpecsDir(...) and do the same for the
restart-time planPath code paths (the block around the later restart logic
referenced at lines ~823-825). Import or reference getSpecsDir and call it with
the same inputs used elsewhere (projectPath and taskId or equivalent) to compute
the spec directory instead of hardcoding ".aperant/specs", and update both
resolvedSpecDir and the restart-time planPath resolution to use getSpecsDir so
all code paths use the same project-specific resolution.
apps/desktop/src/main/project-initializer.ts (1)

301-316: ⚠️ Potential issue | 🟠 Major

Block initialization while legacy .auto-claude data still exists.

initializeProject() still creates .aperant whenever .aperant is missing, even if .auto-claude is present. That can split a project between the legacy and new data folders instead of forcing the rename flow.

🐛 Suggested change
   // Check if already initialized
   const dotAperantPath = path.join(projectPath, '.aperant');
+
+  if (needsMigration(projectPath)) {
+    return {
+      success: false,
+      error: 'Legacy .auto-claude data detected. Migrate the project before initializing.'
+    };
+  }
 
   if (existsSync(dotAperantPath)) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/project-initializer.ts` around lines 301 - 316, The
initializer currently only checks for '.aperant' and will create it even when a
legacy '.auto-claude' folder exists; update initializeProject (the block that
defines dotAperantPath and checks existsSync) to also compute dotAutoClaudePath
= path.join(projectPath, '.auto-claude') and if existsSync(dotAutoClaudePath)
return a failure (similar shape to the existing return) that blocks creation of
'.aperant' and instructs the user to run the rename/migration flow. Ensure you
reference dotAutoClaudePath in the check and do not proceed to
mkdirSync(dotAperantPath) when the legacy folder exists.
apps/desktop/src/main/changelog/changelog-service.ts (1)

55-57: ⚠️ Potential issue | 🟡 Minor

The DEBUG comments still don't describe the actual .env lookup.

loadAperantEnv() reads from the path returned by getAperantSourcePath(), not a literal aperant/.env, so these comments are still misleading.

Also applies to: 81-81, 119-125

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/changelog/changelog-service.ts` around lines 55 - 57,
Update the misleading DEBUG comment to accurately describe where the .env is
loaded from: mention that loadAperantEnv() reads the env file from the path
returned by getAperantSourcePath() (not a literal "aperant/.env") and update any
other DEBUG-related comments (the ones near the
loadAperantEnv/getAperantSourcePath usage and similar comments around the DEBUG
checks) to state that DEBUG is resolved by loading that path and then checking
process.env; adjust wording in the comments near loadAperantEnv(),
getAperantSourcePath(), and any DEBUG-checking helpers so they reflect the
actual lookup behavior.
apps/desktop/src/renderer/App.tsx (1)

381-397: ⚠️ Potential issue | 🟠 Major

Check migration before the init dialog can open.

Line 390 still opens initialization for any selected project without aperantPath, but needsMigration() only runs after openProjectTab() in the add-project paths. That means previously saved legacy projects bypass migration on startup, and newly added ones can still race into competing migrate/init dialogs. Gate the init effect on a per-project “migration check pending” flag and run the same check on selected-project changes.

Also applies to: 419-431, 663-674

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/App.tsx` around lines 381 - 397, The init dialog
effect currently shows initialization whenever a selectedProject lacks
aperantPath, but it must wait for the project's migration check to complete; add
and use a per-project "migration check pending" flag (e.g.,
migrationCheckPending map keyed by project.id or a migrationChecked set) and
ensure the useEffect that shows the init dialog (the effect referencing
selectedProject, skippedInitProjectId, isInitializing, initSuccess) also gates
on migrationCheckPending[selectedProject.id] being false; run the same
needsMigration() invocation that openProjectTab() uses (and set/clear the
pending flag) whenever selectedProject changes so previously-saved legacy
projects don't bypass migration and to avoid racing migrate vs init
dialogs—update calls to setPendingProject/setShowInitDialog to only run after
the migration check finishes and indicates no migration is required.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9272a1fb-2601-42d1-822b-e0ecfe96d13f

📥 Commits

Reviewing files that changed from the base of the PR and between f6bf6d4 and 4c832e6.

📒 Files selected for processing (131)
  • apps/desktop/e2e/flows.e2e.ts
  • apps/desktop/src/__tests__/setup.ts
  • apps/desktop/src/main/__tests__/insights-config.test.ts
  • apps/desktop/src/main/__tests__/project-store.test.ts
  • apps/desktop/src/main/agent/agent-manager.ts
  • apps/desktop/src/main/agent/agent-process.test.ts
  • apps/desktop/src/main/agent/agent-process.ts
  • apps/desktop/src/main/agent/agent-queue.ts
  • apps/desktop/src/main/ai/auth/codex-oauth.ts
  • apps/desktop/src/main/ai/mcp/registry.ts
  • apps/desktop/src/main/ai/prompts/subtask-prompt-generator.ts
  • apps/desktop/src/main/ai/schema/structured-output.ts
  • apps/desktop/src/main/ai/tools/aperant/get-build-progress.ts
  • apps/desktop/src/main/ai/tools/aperant/get-session-context.ts
  • apps/desktop/src/main/ai/tools/aperant/index.ts
  • apps/desktop/src/main/ai/tools/aperant/record-discovery.ts
  • apps/desktop/src/main/ai/tools/aperant/record-gotcha.ts
  • apps/desktop/src/main/ai/tools/aperant/update-qa-status.ts
  • apps/desktop/src/main/ai/tools/aperant/update-subtask-status.ts
  • apps/desktop/src/main/ai/tools/providers/fetch-browse.ts
  • apps/desktop/src/main/ai/worktree/worktree-manager.ts
  • apps/desktop/src/main/changelog/changelog-service.ts
  • apps/desktop/src/main/changelog/generator.ts
  • apps/desktop/src/main/changelog/types.ts
  • apps/desktop/src/main/changelog/version-suggester.ts
  • apps/desktop/src/main/claude-code-settings/index.ts
  • apps/desktop/src/main/config-paths.ts
  • apps/desktop/src/main/index.ts
  • apps/desktop/src/main/insights-service.ts
  • apps/desktop/src/main/insights/README.md
  • apps/desktop/src/main/insights/REFACTORING_NOTES.md
  • apps/desktop/src/main/insights/config.ts
  • apps/desktop/src/main/ipc-handlers/README.md
  • apps/desktop/src/main/ipc-handlers/agent-events-handlers.ts
  • apps/desktop/src/main/ipc-handlers/changelog-handlers.ts
  • apps/desktop/src/main/ipc-handlers/changelog-handlers.ts.bk
  • apps/desktop/src/main/ipc-handlers/claude-code-handlers.ts
  • apps/desktop/src/main/ipc-handlers/context/README.md
  • apps/desktop/src/main/ipc-handlers/context/project-context-handlers.ts
  • apps/desktop/src/main/ipc-handlers/context/utils.ts
  • apps/desktop/src/main/ipc-handlers/env-handlers.ts
  • apps/desktop/src/main/ipc-handlers/github/__tests__/runner-env-handlers.test.ts
  • apps/desktop/src/main/ipc-handlers/github/spec-utils.ts
  • apps/desktop/src/main/ipc-handlers/github/utils.ts
  • apps/desktop/src/main/ipc-handlers/gitlab/spec-utils.ts
  • apps/desktop/src/main/ipc-handlers/gitlab/utils.ts
  • apps/desktop/src/main/ipc-handlers/ideation/idea-manager.ts
  • apps/desktop/src/main/ipc-handlers/ideation/session-manager.ts
  • apps/desktop/src/main/ipc-handlers/ideation/task-converter.ts
  • apps/desktop/src/main/ipc-handlers/insights-handlers.ts
  • apps/desktop/src/main/ipc-handlers/linear-handlers.ts
  • apps/desktop/src/main/ipc-handlers/mcp-handlers.ts
  • apps/desktop/src/main/ipc-handlers/memory-handlers.ts
  • apps/desktop/src/main/ipc-handlers/project-handlers.ts
  • apps/desktop/src/main/ipc-handlers/roadmap-handlers.ts
  • apps/desktop/src/main/ipc-handlers/sections/context-roadmap-section.txt
  • apps/desktop/src/main/ipc-handlers/sections/context_extracted.txt
  • apps/desktop/src/main/ipc-handlers/sections/ideation-insights-section.txt
  • apps/desktop/src/main/ipc-handlers/sections/integration-section.txt
  • apps/desktop/src/main/ipc-handlers/sections/roadmap_extracted.txt
  • apps/desktop/src/main/ipc-handlers/sections/task-section.txt
  • apps/desktop/src/main/ipc-handlers/sections/task_extracted.txt
  • apps/desktop/src/main/ipc-handlers/settings-handlers.ts
  • apps/desktop/src/main/ipc-handlers/task/README.md
  • apps/desktop/src/main/ipc-handlers/task/__tests__/logs-integration.test.ts
  • apps/desktop/src/main/ipc-handlers/task/crud-handlers.ts
  • apps/desktop/src/main/ipc-handlers/task/execution-handlers.ts
  • apps/desktop/src/main/ipc-handlers/task/logs-handlers.ts
  • apps/desktop/src/main/ipc-handlers/task/plan-file-utils.ts
  • apps/desktop/src/main/ipc-handlers/task/worktree-handlers.ts
  • apps/desktop/src/main/ipc-handlers/terminal/worktree-handlers.ts
  • apps/desktop/src/main/project-initializer.ts
  • apps/desktop/src/main/project-store.ts
  • apps/desktop/src/main/release-service.ts
  • apps/desktop/src/main/sentry.ts
  • apps/desktop/src/main/services/profile/profile-manager.ts
  • apps/desktop/src/main/task-state-manager.ts
  • apps/desktop/src/main/terminal-name-generator.ts
  • apps/desktop/src/main/terminal/cli-integration-handler.ts
  • apps/desktop/src/main/terminal/pty-daemon-client.ts
  • apps/desktop/src/main/terminal/pty-daemon.ts
  • apps/desktop/src/main/title-generator.ts
  • apps/desktop/src/main/updater/path-resolver.ts
  • apps/desktop/src/main/utils/git-isolation.ts
  • apps/desktop/src/main/utils/profile-manager.ts
  • apps/desktop/src/main/utils/spec-number-lock.ts
  • apps/desktop/src/preload/api/project-api.ts
  • apps/desktop/src/renderer/App.tsx
  • apps/desktop/src/renderer/__tests__/project-store-tabs.test.ts
  • apps/desktop/src/renderer/components/AddProjectModal.tsx
  • apps/desktop/src/renderer/components/AgentTools.tsx
  • apps/desktop/src/renderer/components/GitHubSetupModal.tsx
  • apps/desktop/src/renderer/components/Sidebar.tsx
  • apps/desktop/src/renderer/components/WelcomeScreen.tsx
  • apps/desktop/src/renderer/components/__tests__/ProjectTabBar.test.tsx
  • apps/desktop/src/renderer/components/__tests__/SortableProjectTab.test.tsx
  • apps/desktop/src/renderer/components/github-issues/README.md
  • apps/desktop/src/renderer/components/linear-import/LinearTaskImportModalRefactored.tsx
  • apps/desktop/src/renderer/components/onboarding/OllamaModelSelector.tsx
  • apps/desktop/src/renderer/components/onboarding/OnboardingWizard.tsx
  • apps/desktop/src/renderer/components/project-settings/AperantIntegration.tsx
  • apps/desktop/src/renderer/components/project-settings/GeneralSettings.tsx
  • apps/desktop/src/renderer/components/project-settings/GitHubIntegrationSection.tsx
  • apps/desktop/src/renderer/components/project-settings/IntegrationSettings.tsx
  • apps/desktop/src/renderer/components/project-settings/LinearIntegrationSection.tsx
  • apps/desktop/src/renderer/components/project-settings/README.md
  • apps/desktop/src/renderer/components/project-settings/hooks/useProjectSettings.ts
  • apps/desktop/src/renderer/components/project-settings/index.ts
  • apps/desktop/src/renderer/components/settings/AdvancedSettings.tsx
  • apps/desktop/src/renderer/components/settings/GeneralSettings.tsx
  • apps/desktop/src/renderer/components/settings/README.md
  • apps/desktop/src/renderer/components/settings/REFACTORING_SUMMARY.md
  • apps/desktop/src/renderer/components/settings/common/InitializationGuard.tsx
  • apps/desktop/src/renderer/components/settings/integrations/GitHubIntegration.tsx
  • apps/desktop/src/renderer/components/settings/integrations/LinearIntegration.tsx
  • apps/desktop/src/renderer/components/settings/sections/SectionRouter.tsx
  • apps/desktop/src/renderer/components/shared/MemoryConfigPanel.tsx
  • apps/desktop/src/renderer/lib/mocks/mock-data.ts
  • apps/desktop/src/renderer/lib/mocks/project-mock.ts
  • apps/desktop/src/renderer/lib/terminal-theme.ts
  • apps/desktop/src/renderer/stores/project-store.ts
  • apps/desktop/src/renderer/stores/settings-store.ts
  • apps/desktop/src/renderer/styles/globals.css
  • apps/desktop/src/shared/constants.ts
  • apps/desktop/src/shared/constants/config.ts
  • apps/desktop/src/shared/types.ts
  • apps/desktop/src/shared/types/ipc.ts
  • apps/desktop/src/shared/types/project.ts
  • apps/desktop/src/shared/types/settings.ts
  • apps/desktop/src/shared/types/task.ts
  • apps/desktop/src/shared/types/terminal.ts

Comment on lines +234 to +236
// Check for aperant directory detection
const aperantPath = path.join(projectPath, '.aperant');
expect(existsSync(aperantPath)).toBe(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Assertion cannot pass because fixture setup still creates auto-claude/ paths.

At Line 236, the .aperant existence check is correct for the rename, but this file still creates and writes test data under auto-claude/ (e.g., Line 25, Line 37, and other path joins). That makes this assertion deterministically fail (matches the pipeline error).

💡 Proposed fix (align all test fixtures/paths in this file to .aperant)
 function setupTestEnvironment(): void {
   TEST_DATA_DIR = mkdtempSync(path.join(os.tmpdir(), 'auto-claude-ui-e2e-'));
   TEST_PROJECT_DIR = path.join(TEST_DATA_DIR, 'test-project');
   mkdirSync(TEST_PROJECT_DIR, { recursive: true });
-  mkdirSync(path.join(TEST_PROJECT_DIR, 'auto-claude', 'specs'), { recursive: true });
+  mkdirSync(path.join(TEST_PROJECT_DIR, '.aperant', 'specs'), { recursive: true });
 }

 function createTestSpec(specId: string, status: 'pending' | 'in_progress' | 'completed' = 'pending'): void {
-  const specDir = path.join(TEST_PROJECT_DIR, 'auto-claude', 'specs', specId);
+  const specDir = path.join(TEST_PROJECT_DIR, '.aperant', 'specs', specId);
   mkdirSync(specDir, { recursive: true });
@@
-    const specDir = path.join(TEST_PROJECT_DIR, 'auto-claude', 'specs', '001-test-spec');
+    const specDir = path.join(TEST_PROJECT_DIR, '.aperant', 'specs', '001-test-spec');
@@
-    const specsDir = path.join(TEST_PROJECT_DIR, 'auto-claude', 'specs');
+    const specsDir = path.join(TEST_PROJECT_DIR, '.aperant', 'specs');
@@
-    const specDir = path.join(TEST_PROJECT_DIR, 'auto-claude', 'specs', specId);
+    const specDir = path.join(TEST_PROJECT_DIR, '.aperant', 'specs', specId);
@@
       TEST_PROJECT_DIR,
-      'auto-claude',
+      '.aperant',
       'specs',
       '001-task',
       'implementation_plan.json'
@@
       TEST_PROJECT_DIR,
-      'auto-claude',
+      '.aperant',
       'specs',
       '001-review',
       'qa_report.md'
@@
       TEST_PROJECT_DIR,
-      'auto-claude',
+      '.aperant',
       'specs',
       '001-reject',
       'QA_FIX_REQUEST.md'
🧰 Tools
🪛 GitHub Actions: E2E

[error] 236-236: E2E test failed: aperant directory detection assertion. Expected existsSync('.aperant') to be true but it was false.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/e2e/flows.e2e.ts` around lines 234 - 236, The assertion checking
for aperantPath (const aperantPath = path.join(projectPath, '.aperant')) fails
because test fixtures still create/write under "auto-claude/" paths; update all
fixture path joins and writes in this file (e.g., any occurrences that build
paths or write files for "auto-claude" around the top-level fixtures and helper
usages) to use ".aperant" instead so that existsSync(aperantPath) returns true;
search for string "auto-claude" and replace with ".aperant" in path.join and
file-write calls referenced by the flows.e2e.ts test so the fixture setup aligns
with the renamed directory.

import type { IdeationConfig } from '../../shared/types';
import { resetStuckSubtasks } from '../ipc-handlers/task/plan-file-utils';
import { AUTO_BUILD_PATHS, getSpecsDir } from '../../shared/constants';
import { APERANT_PATHS, getSpecsDir } from '../../shared/constants';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Prefer path alias import for shared constants.

Switch this changed import to the configured alias form for consistency with repo conventions.

As per coding guidelines apps/desktop/src/**/*.{ts,tsx}: "Use path aliases defined in tsconfig.json for imports: @/* (renderer), @shared/* (shared), @preload/* (preload), @features/*, @components/*, @hooks/*, @lib/*."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/agent/agent-manager.ts` at line 18, The import in
agent-manager.ts should use the repo's TypeScript path alias for shared code;
replace the relative import of APERANT_PATHS and getSpecsDir with the alias form
(e.g., import { APERANT_PATHS, getSpecsDir } from '@shared/constants') so the
code follows the apps/desktop src import conventions and tsconfig aliases.

import { RoadmapConfig } from './types';
import type { IdeationConfig, Idea } from '../../shared/types';
import { AUTO_BUILD_PATHS } from '../../shared/constants';
import { APERANT_PATHS } from '../../shared/constants';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider using path alias for import.

The import uses a relative path instead of the configured @shared/* alias. As per coding guidelines, path aliases should be used for imports in this directory.

♻️ Suggested refactor
-import { APERANT_PATHS } from '../../shared/constants';
+import { APERANT_PATHS } from '@shared/constants';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { APERANT_PATHS } from '../../shared/constants';
import { APERANT_PATHS } from '@shared/constants';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/agent/agent-queue.ts` at line 9, Import in
agent-queue.ts currently uses a relative path to access APERANT_PATHS; replace
the relative import with the configured path alias. Update the import that
references APERANT_PATHS to use the '@shared/constants' alias (keeping the
symbol name APERANT_PATHS unchanged) so the file imports from
'@shared/constants' instead of '../../shared/constants', and ensure
ESLint/tsconfig path mappings still resolve correctly.

Comment on lines 112 to 116
transport: {
type: 'stdio',
command: 'node',
args: ['auto-claude-mcp-server.js'],
args: ['aperant-mcp-server.js'],
env: { SPEC_DIR: specDir },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== MCP server script files ==="
fd -a '^(auto-claude|aperant)-mcp-server\.js$'

echo
echo "=== Old/new script references and packaging config ==="
rg -n -C2 'auto-claude-mcp-server\.js|aperant-mcp-server\.js|process\.resourcesPath|app\.isPackaged|extraResources|asarUnpack|files:' .

echo
echo "=== Registry call sites ==="
rg -n -C3 'createAperantServer|getMcpServerConfig|resolveMcpServers' apps/desktop/src/main

Repository: AndyMik90/Aperant

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Registry file content (lines 100-125) ==="
sed -n '100,125p' apps/desktop/src/main/ai/mcp/registry.ts

echo
echo "=== All MCP-related files ==="
fd -t f -e js -e ts mcp

echo
echo "=== Electron builder config for resources ==="
fd -t f -e json 'electron-builder|package\.json' | head -5
rg -l 'asarUnpack|extraResources|files.*aperant|files.*mcp' . --type json | head -5

Repository: AndyMik90/Aperant

Length of output: 1090


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Electron build config in apps/desktop/package.json ==="
jq '.build' apps/desktop/package.json | head -60

echo
echo "=== Search for script generation or build references ==="
rg -i 'aperant.*mcp|mcp.*server|mcp.*script' --type json --type ts . | grep -v node_modules | head -20

echo
echo "=== Check for separate mcp-server package or directory ==="
find . -type d -name '*mcp*' | grep -v node_modules

echo
echo "=== Look for script imports in registry.ts ==="
head -30 apps/desktop/src/main/ai/mcp/registry.ts

Repository: AndyMik90/Aperant

Length of output: 4166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for where spawned process cwd is set ==="
rg -B5 -A5 'spawning|spawn|execFile|exec.*aperant' apps/desktop/src/main --type ts

echo
echo "=== Check for TODO/FIXME about MCP server script ==="
rg -i 'TODO|FIXME|XXX.*mcp|mcp.*TODO|aperant.*server' apps/desktop/src/main --type ts

echo
echo "=== Look at Memory.md for MCP server guidance ==="
grep -A10 -B2 'mcp.*server\|aperant.*mcp' Memory.md | head -40

Repository: AndyMik90/Aperant

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Where createAperantServer is used ==="
rg -n 'createAperantServer\|getMcpServerConfig' apps/desktop/src/main/ai --type ts -B2 -A2

echo
echo "=== Check how transport commands are actually spawned ==="
rg -n 'transport.*command\|spawn.*command\|spawnSync.*command' apps/desktop/src/main --type ts -B3 -A3 | head -80

Repository: AndyMik90/Aperant

Length of output: 102


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full registry.ts file around function definitions ==="
sed -n '80,150p' apps/desktop/src/main/ai/mcp/registry.ts

echo
echo "=== Search for registry exports and usage ==="
rg -n 'export.*registry\|getRegistry\|createServer' apps/desktop/src/main/ai/mcp --type ts -A3

echo
echo "=== Where MCP servers are initialized (any Stdio transport) ==="
rg -n 'type.*stdio\|stdio' apps/desktop/src/main --type ts -B5 -A5 | head -100

Repository: AndyMik90/Aperant

Length of output: 2191


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for where stdio MCP servers are spawned ==="
rg -n 'stdio.*spawn\|spawn.*command\|ClientTransport\|StdioClientTransport' apps/desktop/src/main --type ts -B5 -A10 | head -120

echo
echo "=== Check Vercel AI SDK usage for MCP initialization ==="
rg -n 'connectToMCP\|createMCPClient\|@modelcontextprotocol' apps/desktop/src/main --type ts | head -20

Repository: AndyMik90/Aperant

Length of output: 115


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full registry.ts file (get file size first) ==="
wc -l apps/desktop/src/main/ai/mcp/registry.ts

echo
echo "=== Full registry.ts content ==="
cat apps/desktop/src/main/ai/mcp/registry.ts

echo
echo "=== Search for MCP client library imports ==="
rg -n '@modelcontextprotocol|mcp|StdioClient' apps/desktop/src/main --type ts | head -30

Repository: AndyMik90/Aperant

Length of output: 9481


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if aperant-mcp-server is an npm package or should exist in repo ==="
rg -i 'aperant.*mcp.*server\|aperant-mcp-server' . --type json --type md | grep -v node_modules | head -20

echo
echo "=== Check root package.json for aperant-mcp-server dependency ==="
jq '.dependencies, .devDependencies' package.json 2>/dev/null | grep -i aperant

echo
echo "=== Check if there's a separate aperant-mcp-server package/repo reference ==="
find . -type f -name '.npmrc' -o -name 'pnpm-workspace.yaml' -o -name 'turbo.json' | xargs cat 2>/dev/null | head -30

Repository: AndyMik90/Aperant

Length of output: 138


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check Memory.md for aperant-mcp-server context ==="
grep -i 'aperant.*mcp\|mcp.*aperant\|build.*management' Memory.md | head -20

echo
echo "=== Check for any .js files in apps/desktop ==="
find apps/desktop -type f -name '*.js' | grep -v node_modules | grep -v dist | grep -v out | head -20

echo
echo "=== Check build/dist output directory structure ==="
ls -la apps/desktop/out/ 2>/dev/null | head -20 || echo "No out/ directory yet (expected - not built)"

echo
echo "=== Check if aperant-mcp-server is supposed to be a separate npm package ==="
grep -r 'aperant-mcp' . --include='*.json' --include='*.md' --include='*.ts' | grep -v node_modules | head -10

Repository: AndyMik90/Aperant

Length of output: 115


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for 'aperant' anywhere in codebase except node_modules ==="
rg 'aperant' --type ts --type json --type md . | grep -v node_modules | head -30

echo
echo "=== Check if this is supposed to be a separate npm package ==="
ls -la | head -20

echo
echo "=== Look for monorepo structure ==="
find . -maxdepth 3 -name 'package.json' -type f | grep -v node_modules | head -10

Repository: AndyMik90/Aperant

Length of output: 3290


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Check if aperant-mcp-server should be built or generated ==="
rg -i 'build.*aperant.*mcp|aperant.*mcp.*build|mcp.*server.*build' apps/desktop --type ts --type json -B2 -A2

echo
echo "=== Check CHANGELOG for aperant-mcp-server mentions ==="
grep -i 'aperant.*mcp\|mcp.*server' CHANGELOG.md | head -10

echo
echo "=== Check build scripts in package.json ==="
jq '.scripts | keys[]' apps/desktop/package.json | grep -i build

echo
echo "=== Does aperant-mcp-server exist as an external npm package? Check package.json ==="
jq '.dependencies, .devDependencies' package.json | grep -i mcp

Repository: AndyMik90/Aperant

Length of output: 1214


The aperant-mcp-server.js script is missing and will fail at runtime.

The code references a script that doesn't exist in the repository and isn't included in the build resources. Unlike other MCP servers (context7, linear, electron, puppeteer) that use npx -y <package-name>, the aperant server uses a bare filename args: ['aperant-mcp-server.js'] that:

  1. Will fail when spawned because the file doesn't exist
  2. Relies on process working directory instead of explicit path resolution
  3. Will definitely break in packaged Electron builds

Either implement the aperant MCP server as an external npm package and use npx -y aperant-mcp-server, or bundle the script in extraResources and resolve its path using app.isPackaged and process.resourcesPath (see Memory.md examples for TreeSitterLoader and vec0 extensions).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ai/mcp/registry.ts` around lines 112 - 116, The
transport configuration in registry.ts uses args: ['aperant-mcp-server.js']
which references a missing script and will fail at runtime; update the aperant
MCP launch to either call the published package via npx (e.g. args: ['-y',
'aperant-mcp-server'] with command 'npx') or bundle the script in extraResources
and resolve its runtime path using app.isPackaged and process.resourcesPath so
the transport.command spawns the correct absolute path to the bundled
aperant-mcp-server.js; modify the transport block (transport.type,
transport.command, transport.args) accordingly and ensure the build includes the
file in extraResources if you choose bundling.

Comment on lines +486 to +496
console.log('[main] Migrating aperantPath from old structure:', validAperantPath, '->', correctedPath);
settings.aperantPath = correctedPath;
validAperantPath = correctedPath;
migrated = true;

// Save the corrected setting - we're the only process modifying settings at startup
try {
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
console.log('[main] Successfully saved migrated autoBuildPath to settings');
console.log('[main] Successfully saved migrated aperantPath to settings');
} catch (writeError) {
console.warn('[main] Failed to save migrated autoBuildPath:', writeError);
console.warn('[main] Failed to save migrated aperantPath:', writeError);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Use the main-process logger for these startup messages.

These new migration/configuration diagnostics still go through console.*, so they disappear in packaged Electron builds. Please route them through the existing logger/Sentry path instead.

As per coding guidelines: apps/desktop/src/main/**/*.ts: Do not use console.log in production code. console.log output is invisible in bundled Electron apps. Use Sentry for error tracking in production; reserve console.log for development only.

Also applies to: 503-510, 519-523

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/index.ts` around lines 486 - 496, Replace
console.log/console.warn calls used for the aperantPath migration (the messages
referencing validAperantPath, correctedPath, settings, settingsPath and the
writeFileSync try/catch that sets migrated) with the main-process logger and
Sentry path: use the app-wide logger (e.g., processLogger or
mainLogger).info(...) for informational migration messages and logger.warn(...)
for the failed save branch, and call Sentry.captureException(writeError) (or the
project’s Sentry wrapper) inside the catch so errors are tracked in production;
apply the same replacement for the other console.* occurrences around the
migration block.

<p className="text-sm font-medium text-foreground">Import Existing Tasks</p>
<p className="text-xs text-muted-foreground mt-1">
Select which Linear issues to import into AutoBuild as tasks.
Select which Linear issues to import into Aperant as tasks.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Replace hardcoded UI copy with react-i18next key

Line 163 introduces hardcoded user-facing text in TSX, which breaks localization. Use t(...) and add matching keys in both en/*.json and fr/*.json.

Suggested change
+import { useTranslation } from 'react-i18next';
...
 function ImportTasksPrompt({ onOpenLinearImport }: ImportTasksPromptProps) {
+  const { t } = useTranslation();
   return (
...
           <p className="text-xs text-muted-foreground mt-1">
-            Select which Linear issues to import into Aperant as tasks.
+            {t('settings.integrations.linear.importTasksPrompt.description')}
           </p>

As per coding guidelines: apps/desktop/src/renderer/**/*.{tsx,jsx}: All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users. Add keys to both en/*.json and fr/*.json translation files.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Select which Linear issues to import into Aperant as tasks.
import { useTranslation } from 'react-i18next';
function ImportTasksPrompt({ onOpenLinearImport }: ImportTasksPromptProps) {
const { t } = useTranslation();
return (
<>
<p className="text-xs text-muted-foreground mt-1">
{t('settings.integrations.linear.importTasksPrompt.description')}
</p>
</>
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/components/settings/integrations/LinearIntegration.tsx`
at line 163, The hardcoded string in the LinearIntegration component should be
replaced with a react-i18next key: import and use useTranslation in the
LinearIntegration.tsx (ensure const { t } = useTranslation()) and replace
"Select which Linear issues to import into Aperant as tasks." with
t('integrations.linear.selectIssues'). Then add the key
"integrations.linear.selectIssues" with the English copy and the French
translation to your en/*.json and fr/*.json translation files respectively so
the UI text is localized.

<div className="rounded-lg border border-warning/30 bg-warning/5 p-3 ml-6">
<p className="text-xs text-warning">
When enabled, new Linear issues will be automatically imported into AutoBuild.
When enabled, new Linear issues will be automatically imported into Aperant.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Localize warning message instead of hardcoding English

Line 206 hardcodes a user-visible warning message. Please switch it to a translation key and add entries in en and fr locale files.

Based on learnings: Applies to apps/desktop/src/renderer/**/*.{tsx,jsx} : All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users. Add keys to both en/*.json and fr/*.json translation files.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/components/settings/integrations/LinearIntegration.tsx`
at line 206, The JSX in the LinearIntegration component currently hardcodes the
warning "When enabled, new Linear issues will be automatically imported into
Aperant."; replace this literal with a react-i18next translation call (use the
existing useTranslation hook or import it if missing) and reference a new key
like "integrations.linear.autoImportWarning" (call
t('integrations.linear.autoImportWarning') where the string is rendered). Then
add matching entries for that key in both the English and French locale JSONs
(en and fr) with the appropriate translated texts. Ensure the key name is unique
and consistent across the component and both locale files so the message is
localized at runtime.

Comment on lines 80 to 83
<SettingsSection
title="General"
description={`Configure Auto-Build, agent model, and notifications for ${project.name}`}
description={`Configure Aperant, agent model, and notifications for ${project.name}`}
>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Localize the new general-section copy.

This new literal bypasses react-i18next. Please move it to a settings key with { projectName } interpolation and add matching entries to both en and fr.

As per coding guidelines, apps/desktop/src/renderer/**/*.{tsx,jsx}: “All frontend user-facing text must use react-i18next translation keys. Hardcoded strings in JSX/TSX break localization for non-English users. Add keys to both en/*.json and fr/*.json translation files.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/settings/sections/SectionRouter.tsx`
around lines 80 - 83, Replace the hardcoded description string in the
SettingsSection inside SectionRouter.tsx with a react-i18next key (e.g.
settings.generalDescription) that uses interpolation for the project name
(projectName -> project.name) and update the component to call
t('settings.generalDescription', { projectName: project.name }); then add
matching translation entries for settings.generalDescription in both English and
French locale JSONs (en/*.json and fr/*.json) with the appropriate interpolated
text (e.g. "Configure Aperant, agent model, and notifications for
{{projectName}}") so the UI uses i18n instead of a literal.

@@ -1,5 +1,5 @@
import { create } from 'zustand';
import type { Project, ProjectSettings, AutoBuildVersionInfo, InitializationResult } from '../../shared/types';
import type { Project, ProjectSettings, AperantVersionInfo, InitializationResult } from '../../shared/types';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Use shared type alias import instead of relative path.

This changed import should follow the configured path alias convention.

As per coding guidelines apps/desktop/src/**/*.{ts,tsx}: "Use path aliases defined in tsconfig.json for imports: @/* (renderer), @shared/* (shared), @preload/* (preload), @features/*, @components/*, @hooks/*, @lib/*."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/project-store.ts` at line 2, Replace the
relative import in project-store.ts with the shared path-alias import; change
the line that imports Project, ProjectSettings, AperantVersionInfo,
InitializationResult from '../../shared/types' to use the configured alias (e.g.
'@shared/types') so the file imports those types via the path alias instead of a
relative path.

Comment on lines +448 to +452
// - Has the aperant source path configured
const hasProviderAccounts = useSettingsStore.getState().providerAccounts.length > 0;
const hasAutoBuildPath = Boolean(settings.autoBuildPath);
const hasAperantPath = Boolean(settings.aperantPath);

const isExistingUser = hasProviderAccounts || hasAutoBuildPath;
const isExistingUser = hasProviderAccounts || hasAperantPath;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

hasProviderAccounts is read before accounts are loaded.

migrateOnboardingCompleted() consults useSettingsStore.getState().providerAccounts, but loadSettings() does not populate that slice until after the migration runs. On a cold start, returning users who only have provider-account credentials still fall through to onboarding. Load the accounts first or query them directly inside the migration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/settings-store.ts` around lines 448 - 452,
migrateOnboardingCompleted currently reads
useSettingsStore.getState().providerAccounts before loadSettings() populates
that slice, causing returning users with only provider accounts to be treated as
new; fix by ensuring provider accounts are available when migration runs—either
call the code that loads provider accounts (via loadSettings()) before invoking
migrateOnboardingCompleted, or modify migrateOnboardingCompleted to fetch
provider accounts directly from the source of truth instead of
useSettingsStore.getState().providerAccounts (so the check for provider accounts
is accurate on cold start).

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review continued from previous batch...

Comment on lines +468 to 474
// Old structure: /path/to/project/aperant or apps/backend
// New structure: /path/to/project/apps/desktop/prompts
let migrated = false;
const possibleCorrections = [
join(validAutoBuildPath.replace(/[/\\]auto-claude[/\\]*$/, ''), 'apps', 'desktop', 'prompts'),
join(validAutoBuildPath.replace(/[/\\]backend[/\\]*$/, ''), 'desktop', 'prompts'),
join(validAperantPath.replace(/[/\\]auto-claude[/\\]*$/, ''), 'apps', 'desktop', 'prompts'),
join(validAperantPath.replace(/[/\\]backend[/\\]*$/, ''), 'desktop', 'prompts'),
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Strip aperant in the stale-path repair too.

The comment says the old structure can end in .../aperant, but the first correction still only removes auto-claude. A saved path like /src/aperant becomes /src/aperant/apps/desktop/prompts, so this repair path never succeeds.

🐛 Suggested change
         const possibleCorrections = [
-          join(validAperantPath.replace(/[/\\]auto-claude[/\\]*$/, ''), 'apps', 'desktop', 'prompts'),
+          join(validAperantPath.replace(/[/\\](?:auto-claude|aperant)[/\\]*$/, ''), 'apps', 'desktop', 'prompts'),
           join(validAperantPath.replace(/[/\\]backend[/\\]*$/, ''), 'desktop', 'prompts'),
         ];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/index.ts` around lines 468 - 474, The stale-path repair
builds possibleCorrections from validAperantPath but only strips "auto-claude",
so paths ending with "aperant" (e.g., /src/aperant) produce invalid corrections;
update the logic that creates possibleCorrections (the array near variables
migrated and validAperantPath) to also strip a trailing "aperant" segment (for
example by using a single replace that matches either "auto-claude" or "aperant"
or by adding an additional replace) so the corrected paths point to the intended
apps/desktop/prompts directory.

Comment on lines +449 to +458
ipcMain.handle(
IPC_CHANNELS.PROJECT_NEEDS_MIGRATION,
async (_, projectId: string): Promise<boolean> => {
try {
const project = projectStore.getProject(projectId);
if (!project) return false;
return needsMigration(project.path);
} catch {
return false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Differentiate “no migration needed” from “migration check failed”.

This handler returns false both when the project is missing and when needsMigration() throws. The renderer then treats those failures as a clean negative and can push a legacy project into the fresh-init path without ever surfacing the real problem. Return an error shape here so callers can stop on detection failures instead of silently falling through.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/project-handlers.ts` around lines 449 -
458, The handler IPC_CHANNELS.PROJECT_NEEDS_MIGRATION currently returns false
for both "no migration needed" and when the check fails; update the handler
registered via ipcMain.handle so its return type is Promise<boolean | { error:
string }>, keep returning a plain boolean from successful checks (e.g.,
needsMigration(project.path) => true/false), but on failure return an error
shape (e.g., { error: 'project not found' } when
projectStore.getProject(projectId) returns null and { error: `migration check
failed: ${err.message}` } inside the catch) so callers can distinguish a
negative result from a failed check; ensure you reference
IPC_CHANNELS.PROJECT_NEEDS_MIGRATION, projectStore.getProject, and
needsMigration when making these changes.

Comment on lines +610 to 615
const aperantSource = getAperantSourcePath();

if (!autoBuildSource) {
if (!aperantSource) {
return {
success: false,
error: 'Auto-build source path not configured'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Rename this fallback error string as well.

This branch still returns 'Auto-build source path not configured', so users can hit the new Aperant flow and still see the old product name.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ipc-handlers/sections/context-roadmap-section.txt`
around lines 610 - 615, The fallback error message returned when aperantSource
is missing still uses the old product name; update the string returned in the
branch that checks getAperantSourcePath() (where aperantSource is evaluated) to
the new product wording (e.g., replace 'Auto-build source path not configured'
with the new Aperant-specific message) so the error text matches the new flow.

Comment on lines +449 to +452
ipcMain.handle(
IPC_CHANNELS.PROJECT_NEEDS_MIGRATION,
async (_, projectId: string): Promise<boolean> => {
try {

This comment was marked as outdated.

Path constants used string interpolation with forward slashes, but the
implementation uses path.join() which produces backslashes on Windows.
The mock existsSync did exact string matching and never found the paths.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/main/__tests__/project-migration.test.ts`:
- Around line 139-155: The test currently only checks that '.auto-claude/' was
replaced with '.aperant/'; update the assertions in the 'updates .gitignore
entries during migration' test (the migrateProject invocation and
fs.writeFileSync inspection using GITIGNORE) to also assert that writtenContent
contains the migrated entries for '.aperant-security.json' and '.aperant-status'
and that it does NOT contain the original '.auto-claude-security.json' and
'.auto-claude-status'; use the same gitignoreWrite retrieval (mock.calls.find on
fs.writeFileSync) and the writtenContent variable to add these four assertions
so regressions in migrateProject for security/status entries are caught.
- Around line 108-172: Add a new unit test that covers the renameSync exception
path: arrange by adding OLD_PATH to mockExistingPaths and stub fs.renameSync to
throw a synthetic Error; call migrateProject(PROJECT); assert the result is {
success: false } and that result.error contains the thrown error message (or
Error object), and assert fs.renameSync was called with OLD_PATH and NEW_PATH.
Reference migrateProject, fs.renameSync, mockExistingPaths, PROJECT, OLD_PATH
and NEW_PATH when adding the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 510bf2f8-f71f-4682-a175-21ae60bd51e9

📥 Commits

Reviewing files that changed from the base of the PR and between 4c832e6 and cba0502.

📒 Files selected for processing (1)
  • apps/desktop/src/main/__tests__/project-migration.test.ts

Comment on lines +108 to +172
describe('migrateProject', () => {
test('successfully renames .auto-claude to .aperant', () => {
mockExistingPaths.add(OLD_PATH);

const result = migrateProject(PROJECT);

expect(result.success).toBe(true);
expect(fs.renameSync).toHaveBeenCalledWith(OLD_PATH, NEW_PATH);
});

test('returns error when .auto-claude does not exist', () => {
// OLD_PATH not in mockExistingPaths

const result = migrateProject(PROJECT);

expect(result.success).toBe(false);
expect(result.error).toMatch(/No \.auto-claude directory/i);
expect(fs.renameSync).not.toHaveBeenCalled();
});

test('returns error when .aperant already exists', () => {
mockExistingPaths.add(OLD_PATH);
mockExistingPaths.add(NEW_PATH);

const result = migrateProject(PROJECT);

expect(result.success).toBe(false);
expect(result.error).toMatch(/\.aperant directory already exists/i);
expect(fs.renameSync).not.toHaveBeenCalled();
});

test('updates .gitignore entries during migration', () => {
mockExistingPaths.add(OLD_PATH);
mockFiles.set(GITIGNORE, '.auto-claude/\n.auto-claude-security.json\n.auto-claude-status\n');

const result = migrateProject(PROJECT);

expect(result.success).toBe(true);
expect(fs.writeFileSync).toHaveBeenCalled();
// Find the call that wrote to the gitignore
const gitignoreWrite = (fs.writeFileSync as ReturnType<typeof vi.fn>).mock.calls.find(
(call: unknown[]) => call[0] === GITIGNORE
);
expect(gitignoreWrite).toBeDefined();
const writtenContent = gitignoreWrite![1] as string;
expect(writtenContent).toContain('.aperant/');
expect(writtenContent).not.toContain('.auto-claude/');
});

test('handles .gitignore not existing gracefully', () => {
mockExistingPaths.add(OLD_PATH);
// mockFiles has no GITIGNORE entry → readFileSync throws ENOENT

// Should not throw; the catch block swallows the .gitignore read error,
// then ensureGitignoreEntries creates the file via writeFileSync
const result = migrateProject(PROJECT);
expect(result.success).toBe(true);
// ensureGitignoreEntries creates a new .gitignore with .aperant/
const written = (fs.writeFileSync as ReturnType<typeof vi.fn>).mock.calls.find(
(call: unknown[]) => call[0] === GITIGNORE
);
expect(written).toBeDefined();
expect(written![1] as string).toContain('.aperant/');
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add an explicit test for the renameSync exception path.

migrateProject has a catch branch that returns { success: false, error }, but no test currently verifies that behavior when the directory rename throws.

🧪 Suggested failure-path test
 describe('migrateProject', () => {
+  test('returns error when renaming directory fails', () => {
+    mockExistingPaths.add(OLD_PATH);
+    (fs.renameSync as ReturnType<typeof vi.fn>).mockImplementationOnce(() => {
+      throw new Error('EACCES: permission denied');
+    });
+
+    const result = migrateProject(PROJECT);
+
+    expect(result.success).toBe(false);
+    expect(result.error).toMatch(/permission denied/i);
+  });
+
   test('successfully renames .auto-claude to .aperant', () => {
As per coding guidelines, "`apps/desktop/**/*.test.{ts,tsx}`: Ensure tests are comprehensive and follow Vitest conventions."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/__tests__/project-migration.test.ts` around lines 108 -
172, Add a new unit test that covers the renameSync exception path: arrange by
adding OLD_PATH to mockExistingPaths and stub fs.renameSync to throw a synthetic
Error; call migrateProject(PROJECT); assert the result is { success: false } and
that result.error contains the thrown error message (or Error object), and
assert fs.renameSync was called with OLD_PATH and NEW_PATH. Reference
migrateProject, fs.renameSync, mockExistingPaths, PROJECT, OLD_PATH and NEW_PATH
when adding the test.

Comment on lines +139 to +155
test('updates .gitignore entries during migration', () => {
mockExistingPaths.add(OLD_PATH);
mockFiles.set(GITIGNORE, '.auto-claude/\n.auto-claude-security.json\n.auto-claude-status\n');

const result = migrateProject(PROJECT);

expect(result.success).toBe(true);
expect(fs.writeFileSync).toHaveBeenCalled();
// Find the call that wrote to the gitignore
const gitignoreWrite = (fs.writeFileSync as ReturnType<typeof vi.fn>).mock.calls.find(
(call: unknown[]) => call[0] === GITIGNORE
);
expect(gitignoreWrite).toBeDefined();
const writtenContent = gitignoreWrite![1] as string;
expect(writtenContent).toContain('.aperant/');
expect(writtenContent).not.toContain('.auto-claude/');
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Strengthen .gitignore assertions to cover all migrated entries.

At Line 153 and Line 154, this test only validates .auto-claude/.aperant/. migrateProject also rewrites .auto-claude-security.json and .auto-claude-status; regressions there would currently pass unnoticed.

✅ Suggested test assertion expansion
     expect(writtenContent).toContain('.aperant/');
     expect(writtenContent).not.toContain('.auto-claude/');
+    expect(writtenContent).toContain('.aperant-security.json');
+    expect(writtenContent).toContain('.aperant-status');
+    expect(writtenContent).not.toContain('.auto-claude-security.json');
+    expect(writtenContent).not.toContain('.auto-claude-status');
As per coding guidelines, "`apps/desktop/**/*.test.{ts,tsx}`: Ensure tests are comprehensive and follow Vitest conventions."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/__tests__/project-migration.test.ts` around lines 139 -
155, The test currently only checks that '.auto-claude/' was replaced with
'.aperant/'; update the assertions in the 'updates .gitignore entries during
migration' test (the migrateProject invocation and fs.writeFileSync inspection
using GITIGNORE) to also assert that writtenContent contains the migrated
entries for '.aperant-security.json' and '.aperant-status' and that it does NOT
contain the original '.auto-claude-security.json' and '.auto-claude-status'; use
the same gitignoreWrite retrieval (mock.calls.find on fs.writeFileSync) and the
writtenContent variable to add these four assertions so regressions in
migrateProject for security/status entries are caught.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/frontend This is frontend only feature New feature or request size/XL Extra large (1000+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant